+/* otfdump.c -- Dump OpenType Layout Tables.
+
+Copyright (C) 2003, 2004, 2008
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO167
+
+This file is part of libotf.
+
+Libotf is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+Libotf is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library, in a file named COPYING; if not,
+write to the Free Software Foundation, Inc., 59 Temple Place, Suite
+330, Boston, MA 02111-1307, USA. */
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libgen.h>
#include <otf.h>
printf (")");
}
-static void
+static int *
dump_coverage (int indent, char *title, OTF_Coverage *coverage)
{
int i;
+ int *char_list;
IPRINT ("(%sCoverage (CoverageFormat %d)",
(title ? title : ""), coverage->CoverageFormat);
{
dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray,
coverage->Count);
+ char_list = malloc (sizeof (int) * (coverage->Count + 1));
+ for (i = 0; i < coverage->Count; i++)
+ char_list[i] = coverage->table.GlyphArray[i];
+ char_list[i] = -1;
}
else
{
+ int n, c;
+
IPRINT ("(RangeCount %d)", coverage->Count);
indent++;
- for (i = 0; i < coverage->Count; i++)
+ for (i = n = 0; i < coverage->Count; i++)
{
IPRINT ("(Range (%d) (Start #x%04X) (End #x%04X)", i,
coverage->table.RangeRecord[i].Start,
IPRINT ("(StartCoverageIndex %d))",
coverage->table.RangeRecord[i].StartCoverageIndex);
indent--;
+ n += (coverage->table.RangeRecord[i].End
+ - coverage->table.RangeRecord[i].Start + 1);
}
+ char_list = malloc (sizeof (int) * (n + 1));
+ for (i = n = 0; i < coverage->Count; i++)
+ for (c = coverage->table.RangeRecord[i].Start;
+ c <= coverage->table.RangeRecord[i].End;
+ c++)
+ char_list[n++] = c;
+ char_list[n] = -1;
}
printf (")");
+ return char_list;
}
static void
IPRINT ("(%s %d)", title, num);
for (i = 0; i < num; i++)
- dump_coverage (indent, NULL, coverage + i);
+ free (dump_coverage (indent, NULL, coverage + i));
}
indent++;
IPRINT ("(StartSize %d) (EndSize %d) (DeltaFormat %d)",
table->StartSize, table->EndSize, table->DeltaFormat);
- IPRINT ("(DeltaValue");
- for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
- printf (" %d", table->DeltaValue[i]);
- printf ("))");
+ if (table->DeltaValue)
+ {
+ IPRINT ("(DeltaValue");
+ for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
+ printf (" %d", table->DeltaValue[i]);
+ printf (")");
+ }
+ printf (")");
}
\f
static void
-dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
+dump_ligature_set_list (int indent, int *char_list,
+ OTF_LigatureSet *ligset, unsigned num)
{
- int i, j;
+ int i, j, k;
IPRINT ("(LigSetCount %d)", num);
for (i = 0; i < num; i++)
ligset[i].Ligature[j].LigGlyph);
dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component,
ligset[i].Ligature[j].CompCount - 1);
+ IPRINT ("(i.e. #x%04X", char_list[i]);
+ for (k = 0; k < ligset[i].Ligature[j].CompCount - 1; k++)
+ printf (" #x%04X", ligset[i].Ligature[j].Component[k]);
+ printf (" = #x%04X)", ligset[i].Ligature[j].LigGlyph);
printf (")");
indent--;
}
}
static void
+dump_pair_set_list (int indent, unsigned count, OTF_PairSet *set)
+{
+ int i, j;
+
+ for (i = 0; i < count; i++)
+ {
+ IPRINT ("(PairSet (%d)", i);
+ indent++;
+ for (j = 0; j < set[i].PairValueCount; j++)
+ {
+ IPRINT ("(PairValueRecord (%d)", j);
+ indent++;
+ IPRINT ("(SecondGlyph #x%04X)",
+ set[i].PairValueRecord[j].SecondGlyph);
+ dump_value_record (indent, "Value1",
+ &set[i].PairValueRecord[j].Value1);
+ dump_value_record (indent, "Value2",
+ &set[i].PairValueRecord[j].Value2);
+ printf (")");
+ indent--;
+ }
+ printf (")");
+ indent--;
+ }
+}
+
+static void
dump_class1_record_list (int indent,
unsigned Class1Count, unsigned Class2Count,
OTF_Class1Record *rec)
}
static void
+dump_entry_exit_list (int indent, unsigned count, OTF_EntryExitRecord *rec)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ IPRINT ("(EntryExitRecord (%d)", i);
+ indent++;
+ dump_anchor (indent, &rec[i].EntryAnchor);
+ dump_anchor (indent, &rec[i].EntryAnchor);
+ printf (")");
+ indent--;
+ }
+}
+
+static void
dump_mark_array (int indent, OTF_MarkArray *array)
{
int i;
IPRINT ("(ChainClassSetCount %d)", count);
for (i = 0; i < count; i++)
- {
- IPRINT ("(ChainClassSet (%d)", i);
- dump_chain_class_rule_list (indent + 1,
- set[i].ChainClassRule,
- set[i].ChainClassRuleCnt);
- printf (")");
- }
+ if (set[i].offset)
+ {
+ IPRINT ("(ChainClassSet (%d)", i);
+ dump_chain_class_rule_list (indent + 1,
+ set[i].ChainClassRule,
+ set[i].ChainClassRuleCnt);
+ printf (")");
+ }
}
case 1:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
IPRINT ("(DeltaGlyhpID #x%04X)",
subtable->u.single1.DeltaGlyphID);
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute,
subtable->u.single2.GlyphCount);
}
case 2:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_sequence_list (indent,
subtable->u.multiple1.Sequence,
subtable->u.multiple1.SequenceCount);
case 3:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet,
subtable->u.alternate1.AlternateSetCount);
}
case 4:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
- dump_ligature_set_list (indent,
+ int *char_list = dump_coverage (indent, NULL, &subtable->Coverage);
+ dump_ligature_set_list (indent, char_list,
subtable->u.ligature1.LigatureSet,
subtable->u.ligature1.LigSetCount);
+ free (char_list);
}
else
printf (" invalid");
case 5:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_rule_set_list (indent, subtable->u.context1.RuleSet,
subtable->u.context1.RuleSetCount);
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
dump_class_set_list (indent, subtable->u.context2.ClassSet,
subtable->u.context2.ClassSetCnt);
case 6:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_chain_rule_set_list
(indent,
subtable->u.chain_context1.ChainRuleSet,
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_class_def (indent, "BacktrackClassDef",
&subtable->u.chain_context2.BacktrackClassDef);
dump_class_def (indent, "InputClassDef",
break;
case 7:
+ IPRINT ("(ExtensionLookupType %d)",
+ subtable->u.extension1.ExtensionLookupType);
+ IPRINT ("(ExtensionOffset %d)",
+ subtable->u.extension1.ExtensionOffset);
+ dump_lookup_subtable_gsub (indent, index,
+ subtable->u.extension1.ExtensionLookupType,
+ subtable->u.extension1.ExtensionSubtable);
+ break;
+
case 8:
- printf (" not-yet-substcount");
+ printf (" not-yet-supported");
break;
default:
case 1:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
IPRINT ("(ValueFormat #x%04X)",
subtable->u.single1.ValueFormat);
dump_value_record (indent, "Value", &subtable->u.single1.Value);
{
int i;
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
IPRINT ("(ValueFormat #x%04X)",
subtable->u.single2.ValueFormat);
IPRINT ("(ValueCount %d)",
case 2:
if (subtable->Format == 1)
{
- printf (" not-yet-supported");
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
+ IPRINT ("(ValueFormat1 #x%04X)",
+ subtable->u.pair1.ValueFormat1);
+ IPRINT ("(ValueFormat2 #x%04X)",
+ subtable->u.pair1.ValueFormat2);
+ dump_pair_set_list (indent, subtable->u.pair1.PairSetCount,
+ subtable->u.pair1.PairSet);
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
IPRINT ("(ValueFormat1 #x%04X)",
subtable->u.pair2.ValueFormat1);
IPRINT ("(ValueFormat2 #x%04X)",
case 3:
if (subtable->Format == 1)
{
- printf (" not-yet-supported");
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
+ dump_entry_exit_list (indent, subtable->u.cursive1.EntryExitCount,
+ subtable->u.cursive1.EntryExitRecord);
}
else
printf (" invalid");
case 4:
if (subtable->Format == 1)
{
- dump_coverage (indent, "Mark", &subtable->Coverage);
- dump_coverage (indent, "Base",
- &subtable->u.mark_base1.BaseCoverage);
+ free (dump_coverage (indent, "Mark", &subtable->Coverage));
+ free (dump_coverage (indent, "Base",
+ &subtable->u.mark_base1.BaseCoverage));
IPRINT ("(ClassCount %d)",
subtable->u.mark_base1.ClassCount);
dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
case 5:
if (subtable->Format == 1)
{
- printf (" not-yet-supported");
+ OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
+ int i, j, k;
+
+ free (dump_coverage (indent, "Mark", &subtable->Coverage));
+ free (dump_coverage (indent, "Ligature",
+ &mark_lig1->LigatureCoverage));
+ IPRINT ("(ClassCount %d)", mark_lig1->ClassCount);
+ dump_mark_array (indent, &mark_lig1->MarkArray);
+ IPRINT ("(LigatureArray (%d)",
+ mark_lig1->LigatureArray.LigatureCount);
+ indent++;
+ for (i = 0; i < mark_lig1->LigatureArray.LigatureCount; i++)
+ {
+ OTF_LigatureAttach *attach
+ = mark_lig1->LigatureArray.LigatureAttach + i;
+
+ IPRINT ("(LigatureAttach (%d)", attach->ComponentCount);
+ indent++;
+ for (j = 0; j < attach->ComponentCount; j++)
+ {
+ OTF_ComponentRecord *rec = attach->ComponentRecord + j;
+
+ IPRINT ("(LigatureAnchor (%d)", mark_lig1->ClassCount);
+ for (k = 0; k < mark_lig1->ClassCount; k++)
+ if (rec->LigatureAnchor[k].AnchorFormat)
+ dump_anchor (indent + 1, rec->LigatureAnchor + k);
+ printf (")");
+ }
+ printf (")");
+ indent--;
+ }
+ printf (")");
}
else
printf (" invalid");
case 6:
if (subtable->Format == 1)
{
- dump_coverage (indent, "Mark1", &subtable->Coverage);
- dump_coverage (indent, "Mark2",
- &subtable->u.mark_mark1.Mark2Coverage);
+ free (dump_coverage (indent, "Mark1", &subtable->Coverage));
+ free (dump_coverage (indent, "Mark2",
+ &subtable->u.mark_mark1.Mark2Coverage));
IPRINT ("(ClassCount %d)",
subtable->u.mark_mark1.ClassCount);
dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
case 7:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_rule_set_list (indent, subtable->u.context1.RuleSet,
subtable->u.context1.RuleSetCount);
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
dump_class_set_list (indent, subtable->u.context2.ClassSet,
subtable->u.context2.ClassSetCnt);
case 8:
if (subtable->Format == 1)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_chain_rule_set_list
(indent,
subtable->u.chain_context1.ChainRuleSet,
}
else if (subtable->Format == 2)
{
- dump_coverage (indent, NULL, &subtable->Coverage);
+ free (dump_coverage (indent, NULL, &subtable->Coverage));
dump_class_def (indent, "BacktrackClassDef",
&subtable->u.chain_context2.BacktrackClassDef);
dump_class_def (indent, "InputClassDef",
else
printf (" invalid");
break;
+
+ case 9:
+ if (subtable->Format == 1)
+ {
+ IPRINT ("(ExtensionLookupType %d)",
+ subtable->u.extension1.ExtensionLookupType);
+ IPRINT ("(ExtensionOffset %d)",
+ subtable->u.extension1.ExtensionOffset);
+ dump_lookup_subtable_gpos
+ (indent, index,
+ subtable->u.extension1.ExtensionLookupType,
+ subtable->u.extension1.ExtensionSubtable);
+ }
+ else
+ printf (" invalid");
}
printf (")");
}
IPRINT ("(LigCaretList");
indent++;
- dump_coverage (indent, NULL, &list->Coverage);
+ free (dump_coverage (indent, NULL, &list->Coverage));
IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
for (i = 0; i < list->LigGlyphCount; i++)
{
printf (")");
}
break;
+
+ case 12:
+ {
+ OTF_EncodingSubtable12 *sub12
+ = cmap->EncodingRecord[i].subtable.f.f12;
+ int j;
+
+ for (j = 0; j < sub12->nGroups; j++)
+ {
+ IPRINT ("(Group (#x%X) (startChar #x%04X) (endChar #x%04X) (startGlyphID #x%X))",
+ j,
+ sub12->Groups[j].startCharCode,
+ sub12->Groups[j].endCharCode,
+ sub12->Groups[j].startGlyphID);
+ }
+ }
+ break;
+
+ case 14:
+ {
+ OTF_EncodingSubtable14 *sub14
+ = cmap->EncodingRecord[i].subtable.f.f14;
+ unsigned j,k;
+
+ IPRINT ("(VariationSelectorRecords %d)",sub14->nRecords);
+ for (j = 0; j < sub14->nRecords; j++)
+ {
+ OTF_VariationSelectorRecord *record = sub14->Records + j;
+ IPRINT ("(VariationSelectorRecord (varSelector #x%x)",
+ record->varSelector);
+ indent += 1;
+ IPRINT ("(defaultUVSOffset #x%x)",
+ record->defaultUVSOffset);
+ if (record->defaultUVSOffset)
+ {
+ IPRINT ("(defaultUVS");
+ indent += 1;
+ for (k = 0 ; k < record->numUnicodeValueRanges; k++)
+ {
+ OTF_UnicodeValueRange *unicodeValueRange
+ = &record->unicodeValueRanges[k];
+ IPRINT("(startUnicodeValue #x%x) (additionalCount %d)",
+ unicodeValueRange->startUnicodeValue,
+ unicodeValueRange->additionalCount);
+ }
+ printf (")");
+ indent -= 1;
+ }
+ IPRINT ("(nonDefaultUVSOffset #x%x)",
+ record->nonDefaultUVSOffset);
+ if (record->nonDefaultUVSOffset)
+ {
+ IPRINT ("(NonDefaultUVS");
+ indent += 1;
+ for (k=0; k < record->numUVSMappings; k++)
+ {
+ OTF_UVSMapping *uvsMapping
+ = &record->uvsMappings[k];
+ IPRINT("(unicodeValue #x%x) (glyphID %d)",
+ uvsMapping->unicodeValue,
+ uvsMapping->glyphID);
+ }
+ printf (")");
+ indent -= 1;
+ }
+ printf (")");
+ indent -= 1;
+ }
+ }
}
indent -= 2;
{
OTF *otf;
- if (argc != 2)
+ if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
{
- fprintf (stderr, "Usage, dtfdump OTF-FILE");
- exit (1);
+ fprintf (stderr, "Usage: %s OTF-FILE\n", basename (argv[0]));
+ exit (argc != 2);
}
otf = OTF_open (argv[1]);