From: handa Date: Thu, 23 Jan 2003 12:38:28 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: REL-0-9-1~110 X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c045c3e7474b15e87c7f334f6523b37af256cb31;p=m17n%2Flibotf.git *** empty log message *** --- diff --git a/example/otfdump.c b/example/otfdump.c index 65f5a97..f788c55 100644 --- a/example/otfdump.c +++ b/example/otfdump.c @@ -73,13 +73,15 @@ dump_head_table (int indent, OTF_head *head) /* COMMON */ static void -dump_glyph_ids (OTF_GlyphID *ids, unsigned num) +dump_glyph_ids (int indent, char *title, OTF_GlyphID *ids, unsigned count) { - while (num-- > 0) + IPRINT ("(%s (count %d)", title, count); + while (count-- > 0) { printf (" #x%04X", *ids); ids++; } + printf (")"); } static void @@ -92,10 +94,8 @@ dump_coverage (int indent, char *title, OTF_Coverage *coverage) indent++; if (coverage->CoverageFormat == 1) { - IPRINT ("(GlyphCount %d)", coverage->Count); - IPRINT ("(GlyphArray"); - dump_glyph_ids (coverage->table.GlyphArray, coverage->Count); - printf (")"); + dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray, + coverage->Count); } else { @@ -223,32 +223,33 @@ dump_class_def (int indent, char *title, OTF_ClassDef *class) IPRINT ("(%s (offset #x%04X) (ClassFormat %d)", (title ? title : "ClassDef"), class->offset, class->ClassFormat); - indent++; - if (class->ClassFormat == 1) + if (class->offset) { - IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph); - IPRINT ("(GlyphCount %d)", class->f.f1.GlyphCount); - IPRINT ("(ClassValueArray"); - dump_glyph_ids ((OTF_GlyphID *) class->f.f1.ClassValueArray, - class->f.f1.GlyphCount); - printf (")"); - } - else if (class->ClassFormat == 2) - { - int i; - - IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount); - IPRINT ("(ClassRangeRecord"); indent++; - for (i = 0; i < class->f.f2.ClassRangeCount; i++) - IPRINT ("((Start #x%04X) (End #x%04X) (class %d))", - class->f.f2.ClassRangeRecord[i].Start, - class->f.f2.ClassRangeRecord[i].End, - class->f.f2.ClassRangeRecord[i].Class); - printf (")"); + if (class->ClassFormat == 1) + { + IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph); + dump_glyph_ids (indent, "ClassValueArray", + (OTF_GlyphID *) class->f.f1.ClassValueArray, + class->f.f1.GlyphCount); + } + else if (class->ClassFormat == 2) + { + int i; + + IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount); + IPRINT ("(ClassRangeRecord"); + indent++; + for (i = 0; i < class->f.f2.ClassRangeCount; i++) + IPRINT ("((Start #x%04X) (End #x%04X) (class %d))", + class->f.f2.ClassRangeRecord[i].Start, + class->f.f2.ClassRangeRecord[i].End, + class->f.f2.ClassRangeRecord[i].Class); + printf (")"); + } + else + printf (" UnknownClassFormat"); } - else - printf ("UknownClassFormat"); printf (")"); } @@ -299,16 +300,30 @@ dump_sequence_list (int indent, OTF_Sequence *sequence, unsigned num) { IPRINT ("(Sequence (%d) (offset #x%04X)", i, sequence[i].offset); - indent++; - IPRINT ("(GlyphCount %d)", sequence[i].GlyphCount); - IPRINT ("(Substitute"); - dump_glyph_ids (sequence[i].Substitute, sequence[i].GlyphCount); - printf ("))"); - indent--; + dump_glyph_ids (indent + 1, "Substitute", sequence[i].Substitute, + sequence[i].GlyphCount); + printf (")"); } } static void +dump_alternate_set_list (int indent, OTF_AlternateSet *altset, unsigned num) +{ + int i; + + IPRINT ("(AlternateSetCount %d)", num); + for (i = 0; i < num; i++) + { + IPRINT ("(AlternateSet (%d) (offset #x%04X)", + i, altset[i].offset); + dump_glyph_ids (indent + 1, "Alternate", altset[i].Alternate, + altset[i].GlyphCount); + printf (")"); + } +} + + +static void dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num) { int i, j; @@ -326,12 +341,9 @@ dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num) indent++; IPRINT ("(LigGlyph #x%04X)", ligset[i].Ligature[j].LigGlyph); - IPRINT ("(ComCount %d)", - ligset[i].Ligature[j].CompCount); - IPRINT ("(Component"); - dump_glyph_ids (ligset[i].Ligature[j].Component, + dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component, ligset[i].Ligature[j].CompCount - 1); - printf ("))"); + printf (")"); indent--; } indent--; @@ -401,17 +413,17 @@ dump_mark_array (int indent, OTF_MarkArray *array) } static void -dump_base_array (int indent, unsigned ClassCount, OTF_BaseArray *array) +dump_anchor_array (int indent, unsigned ClassCount, OTF_AnchorArray *array) { int i, j; - IPRINT ("(BaseArray (BaseCount %d)", array->BaseCount); + IPRINT ("(AnchorArray (Count %d)", array->Count); indent++; - for (i = 0; i < array->BaseCount; i++) + for (i = 0; i < array->Count; i++) { - IPRINT ("(BaseRecord (%d) ", i); + IPRINT ("(AnchorRecord (%d) ", i); for (j = 0; j < ClassCount; j++) - dump_anchor (indent + 1, array->BaseRecord[i].BaseAnchor + j); + dump_anchor (indent + 1, array->AnchorRecord[i].Anchor + j); printf (")"); } printf (")"); @@ -419,15 +431,14 @@ dump_base_array (int indent, unsigned ClassCount, OTF_BaseArray *array) static void -dump_subst_lookup_record_list (int indent, - OTF_SubstLookupRecord *rec, unsigned num) +dump_lookup_record_list (int indent, OTF_LookupRecord *rec, unsigned num) { int i; - IPRINT ("(SubstCount %d)", num); + IPRINT ("(LookupCount %d)", num); for (i = 0; i < num; i++) { - IPRINT ("(SubstLookupRecord (%d)", i); + IPRINT ("(LookupRecord (%d)", i); indent++; IPRINT ("(SequenceIndex %d)", rec[i].SequenceIndex); IPRINT ("(LookupListIndex %d))", rec[i].LookupListIndex); @@ -473,6 +484,151 @@ dump_lookup_list (int indent, OTF_LookupList *list, int gsub) printf (")"); } +static void +dump_rule_list (int indent, OTF_Rule *rule, int count) +{ + int i; + + IPRINT ("(RuleCount %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(Rule (%d)", i); + indent++; + IPRINT ("(GlyphCount %d)", rule[i].GlyphCount); + IPRINT ("(LookupCount %d)", rule[i].LookupCount); + dump_glyph_ids (indent, "Input", rule[i].Input, rule[i].GlyphCount - 1); + dump_lookup_record_list (indent, rule[i].LookupRecord, + rule[i].LookupCount); + printf (")"); + indent--; + } +} + +static void +dump_rule_set_list (int indent, OTF_RuleSet *set, int count) +{ + int i; + + IPRINT ("(RuleSetCount %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(RuleSet (%d)", i); + dump_rule_list (indent + 1, set[i].Rule, set[i].RuleCount); + printf (")"); + } +} + +static void +dump_class_rule_list (int indent, OTF_ClassRule *rule, int count) +{ + int i, j; + + IPRINT ("(ClassRuleCnt %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(ClassRule (%d)", i); + indent++; + IPRINT ("(GlyphCount %d)", rule[i].GlyphCount); + IPRINT ("(LookupCount %d)", rule[i].LookupCount); + IPRINT ("(Class"); + for (j = 0; j < rule[i].GlyphCount - 1; j++) + printf (" %d", rule[i].Class[j]); + printf (")"); + dump_lookup_record_list (indent, rule[i].LookupRecord, + rule[i].LookupCount); + printf (")"); + indent--; + } +} + +static void +dump_class_set_list (int indent, OTF_ClassSet *set, int count) +{ + int i; + + IPRINT ("(ClassSetCount %d)", count); + for (i = 0; i < count; i++) + if (set[i].offset) + { + IPRINT ("(ClassSet (%d)", i); + dump_class_rule_list (indent + 1, set[i].ClassRule, + set[i].ClassRuleCnt); + printf (")"); + } +} + +static void +dump_chain_rule_list (int indent, OTF_ChainRule *rule, int count) +{ + int i; + + IPRINT ("(ChainRuleCount %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(ChainRule (%d)", i); + dump_glyph_ids (indent + 1, "Backtrack", + rule[i].Backtrack, rule[i].BacktrackGlyphCount); + dump_glyph_ids (indent + 1, "Input", + rule[i].Input, rule[i].InputGlyphCount - 1); + dump_glyph_ids (indent + 1, "LookAhead", + rule[i].LookAhead, rule[i].LookaheadGlyphCount); + dump_lookup_record_list (indent + 1, rule[i].LookupRecord, + rule[i].LookupCount); + printf (")"); + } +} + +static void +dump_chain_rule_set_list (int indent, OTF_ChainRuleSet *set, int count) +{ + int i; + + IPRINT ("(ChainRuleSetCount %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(ChainRuleSet (%d)", i); + dump_chain_rule_list (indent + 1, + set[i].ChainRule, set[i].ChainRuleCount); + printf (")"); + } +} + +static void +dump_chain_class_rule_list (int indent, OTF_ChainClassRule *rule, int count) +{ + int i; + + IPRINT ("(ChainClassRuleCount %d)", count); + for (i = 0; i < count; i++) + { + IPRINT ("(ChainClassRule (%d)", i); + dump_glyph_ids (indent + 1, "Backtrack", + rule[i].Backtrack, rule[i].BacktrackGlyphCount); + dump_glyph_ids (indent + 1, "Input", + rule[i].Input, rule[i].InputGlyphCount - 1); + dump_glyph_ids (indent + 1, "LookAhead", + rule[i].LookAhead, rule[i].LookaheadGlyphCount); + dump_lookup_record_list (indent + 1, rule[i].LookupRecord, + rule[i].LookupCount); + printf (")"); + } +} + +static void +dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count) +{ + 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 (")"); + } +} /* GSUB */ @@ -495,13 +651,11 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, else if (subtable->Format == 2) { dump_coverage (indent, NULL, &subtable->Coverage); - IPRINT ("(GlyphCount %d)", - subtable->u.single2.GlyphCount); - IPRINT ("(Substitute"); - dump_glyph_ids (subtable->u.single2.Substitute, + dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute, subtable->u.single2.GlyphCount); - printf (")"); } + else + printf (" invalid"); break; case 2: @@ -512,8 +666,21 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, subtable->u.multiple1.Sequence, subtable->u.multiple1.SequenceCount); } + else + printf (" invalid"); break; + case 3: + if (subtable->Format == 1) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet, + subtable->u.alternate1.AlternateSetCount); + } + else + printf (" invalid"); + break; + case 4: if (subtable->Format == 1) { @@ -522,36 +689,59 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, subtable->u.ligature1.LigatureSet, subtable->u.ligature1.LigSetCount); } + else + printf (" invalid"); + break; + + case 5: + if (subtable->Format == 1) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_rule_set_list (indent, subtable->u.context1.SubRuleSet, + subtable->u.context1.SubRuleSetCount); + } + else if (subtable->Format == 2) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_class_def (indent, NULL, &subtable->u.context2.ClassDef); + dump_class_set_list (indent, subtable->u.context2.SubClassSet, + subtable->u.context2.SubClassSetCnt); + } + else if (subtable->Format == 3) + { + dump_coverage_list (indent, "Coverage", + subtable->u.context3.Coverage, + subtable->u.context3.GlyphCount); + dump_lookup_record_list (indent, + subtable->u.context3.LookupRecord, + subtable->u.context3.SubstCount); + } + else + printf (" invalid"); break; case 6: if (subtable->Format == 1) { -#if 0 - read_coverage (fp, offset, - &subtable->u.chain_context1.Coverage); - subtable->u.chain_context1.ChainSubRuleSetCount - = (read_chain_subrule_set - (fp, offset, - &subtable->u.chain_context1.ChainSubRuleSet)); -#endif + dump_coverage (indent, NULL, &subtable->Coverage); + dump_chain_rule_set_list + (indent, + subtable->u.chain_context1.ChainSubRuleSet, + subtable->u.chain_context1.ChainSubRuleSetCount); } else if (subtable->Format == 2) { -#if 0 - read_coverage (fp, offset, - &subtable->u.chain_context2.Coverage); - read_class_def (fp, offset, + dump_coverage (indent, NULL, &subtable->Coverage); + dump_class_def (indent, "BacktrackClassDef", &subtable->u.chain_context2.Backtrack); - read_class_def (fp, offset, + dump_class_def (indent, "InputClassDef", &subtable->u.chain_context2.Input); - read_class_def (fp, offset, + dump_class_def (indent, "LookaheadClassDef", &subtable->u.chain_context2.LookAhead); - subtable->u.chain_context2.ChainSubClassSetCnt - = (read_chain_subclass_set - (fp, offset, - &subtable->u.chain_context2.ChainSubClassSet)); -#endif + dump_chain_class_set_list + (indent, + subtable->u.chain_context2.ChainSubClassSet, + subtable->u.chain_context2.ChainSubClassSetCnt); } else if (subtable->Format == 3) { @@ -564,15 +754,25 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, subtable->u.chain_context3.Input, subtable->u.chain_context3.InputGlyphCount); dump_coverage_list - (indent, "LookaheaGlyphCount", + (indent, "LookaheadGlyphCount", subtable->u.chain_context3.LookAhead, subtable->u.chain_context3.LookaheadGlyphCount); - dump_subst_lookup_record_list + dump_lookup_record_list (indent, - subtable->u.chain_context3.SubstLookupRecord, + subtable->u.chain_context3.LookupRecord, subtable->u.chain_context3.SubstCount); } + else + printf (" invalid"); + break; + + case 7: + case 8: + printf (" not-yet-substcount"); break; + + default: + printf (" invalid"); } printf (")"); } @@ -607,30 +807,33 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, switch (type) { case 1: -#if 0 if (subtable->Format == 1) { - dump_coverage (indent, NULL, &subtable->u.single1.Coverage); - IPRINT ("(DeltaGlyhpID #x%04X)", - subtable->u.single1.DeltaGlyphID); + dump_coverage (indent, NULL, &subtable->Coverage); + IPRINT ("(ValueFormat #x%04X)", + subtable->u.single1.ValueFormat); + dump_value_record (indent, "Value", &subtable->u.single1.Value); } else if (subtable->Format == 2) { - dump_coverage (indent, NULL, &subtable->u.single2.Coverage); - IPRINT ("(GlyphCount %d)", - subtable->u.single2.GlyphCount); - IPRINT ("(Substitute"); - dump_glyph_ids (subtable->u.single2.Substitute, - subtable->u.single2.GlyphCount); - printf (")"); + int i; + + dump_coverage (indent, NULL, &subtable->Coverage); + IPRINT ("(ValueFormat #x%04X)", + subtable->u.single2.ValueFormat); + IPRINT ("(ValueCount %d)", + subtable->u.single2.ValueCount); + for (i = 0; i < subtable->u.single2.ValueCount; i++) + dump_value_record (indent, "Value", &subtable->u.single2.Value[i]); } -#endif + else + printf (" invalid"); break; case 2: if (subtable->Format == 1) { - dump_coverage (indent, NULL, &subtable->Coverage); + printf (" not-yet-supported"); } else if (subtable->Format == 2) { @@ -652,8 +855,19 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, subtable->u.pair2.Class2Count, subtable->u.pair2.Class1Record); } + else + printf (" invalid"); break; + case 3: + if (subtable->Format == 1) + { + printf (" not-yet-supported"); + } + else + printf (" invalid"); + break; + case 4: if (subtable->Format == 1) { @@ -663,43 +877,88 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, IPRINT ("(ClassCount %d)", subtable->u.mark_base1.ClassCount); dump_mark_array (indent, &subtable->u.mark_base1.MarkArray); - dump_base_array (indent, subtable->u.mark_base1.ClassCount, + dump_anchor_array (indent, subtable->u.mark_base1.ClassCount, &subtable->u.mark_base1.BaseArray); } break; + case 5: + if (subtable->Format == 1) + { + printf (" not-yet-supported"); + } + else + printf (" invalid"); + break; + case 6: if (subtable->Format == 1) { -#if 0 - read_coverage (fp, offset, - &subtable->u.chain_context1.Coverage); - subtable->u.chain_context1.ChainSubRuleSetCount - = (read_chain_subrule_set - (fp, offset, - &subtable->u.chain_context1.ChainSubRuleSet)); -#endif + dump_coverage (indent, "Mark1", &subtable->Coverage); + 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); + dump_anchor_array (indent, subtable->u.mark_mark1.ClassCount, + &subtable->u.mark_mark1.Mark2Array); + } + else + printf (" invalid"); + break; + + case 7: + if (subtable->Format == 1) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_rule_set_list (indent, subtable->u.context1.PosRuleSet, + subtable->u.context1.PosRuleSetCount); } else if (subtable->Format == 2) { -#if 0 - read_coverage (fp, offset, - &subtable->u.chain_context2.Coverage); - read_class_def (fp, offset, + dump_coverage (indent, NULL, &subtable->Coverage); + dump_class_def (indent, NULL, &subtable->u.context2.ClassDef); + dump_class_set_list (indent, subtable->u.context2.PosClassSet, + subtable->u.context2.PosClassSetCnt); + } + else if (subtable->Format == 3) + { + dump_coverage_list (indent, "Coverage", + subtable->u.context3.Coverage, + subtable->u.context3.GlyphCount); + dump_lookup_record_list (indent, + subtable->u.context3.LookupRecord, + subtable->u.context3.PosCount); + } + else + printf (" invalid"); + break; + + case 8: + if (subtable->Format == 1) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_chain_rule_set_list + (indent, + subtable->u.chain_context1.ChainPosRuleSet, + subtable->u.chain_context1.ChainPosRuleSetCount); + } + else if (subtable->Format == 2) + { + dump_coverage (indent, NULL, &subtable->Coverage); + dump_class_def (indent, "BacktrackClassDef", &subtable->u.chain_context2.Backtrack); - read_class_def (fp, offset, + dump_class_def (indent, "InputClassDef", &subtable->u.chain_context2.Input); - read_class_def (fp, offset, + dump_class_def (indent, "LookaheadClassDef", &subtable->u.chain_context2.LookAhead); - subtable->u.chain_context2.ChainSubClassSetCnt - = (read_chain_subclass_set - (fp, offset, - &subtable->u.chain_context2.ChainSubClassSet)); -#endif + dump_chain_class_set_list + (indent, + subtable->u.chain_context2.ChainPosClassSet, + subtable->u.chain_context2.ChainPosClassSetCnt); } else if (subtable->Format == 3) { -#if 0 dump_coverage_list (indent, "BackTrackGlyphCount", subtable->u.chain_context3.Backtrack, @@ -712,12 +971,13 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, (indent, "LookaheaGlyphCount", subtable->u.chain_context3.LookAhead, subtable->u.chain_context3.LookaheadGlyphCount); - dump_subst_lookup_record_list + dump_lookup_record_list (indent, - subtable->u.chain_context3.SubstLookupRecord, - subtable->u.chain_context3.SubstCount); -#endif + subtable->u.chain_context3.LookupRecord, + subtable->u.chain_context3.PosCount); } + else + printf (" invalid"); break; } printf (")"); diff --git a/example/otfview.c b/example/otfview.c index d5dc341..79eb728 100644 --- a/example/otfview.c +++ b/example/otfview.c @@ -143,7 +143,12 @@ main (int argc, char **argv) } otf = OTF_open (argv[1]); - if (! otf) + if (! otf + || OTF_get_table (otf, "head") < 0 + || OTF_get_table (otf, "cmap") < 0 + || OTF_get_table (otf, "GDEF") < 0 + || OTF_get_table (otf, "GSUB") < 0 + || OTF_get_table (otf, "GPOS") < 0) { OTF_perror ("otfview"); exit (1); diff --git a/src/otf.h b/src/otf.h index 56d1a8f..c84368e 100644 --- a/src/otf.h +++ b/src/otf.h @@ -535,58 +535,59 @@ typedef struct { unsigned SequenceIndex; unsigned LookupListIndex; -} OTF_SubstLookupRecord; +} OTF_LookupRecord; -typedef struct OTF_SubRuleSet OTF_SubRuleSet; +typedef struct OTF_RuleSet OTF_RuleSet; typedef struct { unsigned SubRuleSetCount; - OTF_SubRuleSet *SubRuleSet; + OTF_RuleSet *SubRuleSet; /* [] */ } OTF_GSUB_Context1; -typedef struct OTF_SubRule OTF_SubRule; +typedef struct OTF_Rule OTF_Rule; -struct OTF_SubRuleSet +struct OTF_RuleSet { OTF_Offset offset; - unsigned SubRuleCount; - OTF_SubRule *SubRule; + unsigned RuleCount; + OTF_Rule *Rule; /* [] */ }; -struct OTF_SubRule +struct OTF_Rule { OTF_Offset offset; unsigned GlyphCount; - unsigned SubstCount; - OTF_GlyphID *Input; - OTF_SubstLookupRecord *SubstLookupRecord; + unsigned LookupCount; + OTF_GlyphID *Input; /* [ - 1] */ + OTF_LookupRecord *LookupRecord; /* [] */ }; -typedef struct OTF_SubClassSet OTF_SubClassSet; +typedef struct OTF_ClassSet OTF_ClassSet; typedef struct { OTF_ClassDef ClassDef; - unsigned SubClassSetCount; - OTF_SubClassSet *SubClassSet; + unsigned SubClassSetCnt; + OTF_ClassSet *SubClassSet; /* [] */ } OTF_GSUB_Context2; -typedef struct OTF_SubClassRule OTF_SubClassRule; +typedef struct OTF_ClassRule OTF_ClassRule; -struct OTF_SubClassSet +struct OTF_ClassSet { - unsigned SubClassRuleCnt; - OTF_SubClassRule *SubClassRule; + OTF_Offset offset; + unsigned ClassRuleCnt; + OTF_ClassRule *ClassRule; /* [] */ }; -struct OTF_SubClassRule +struct OTF_ClassRule { OTF_Offset offset; unsigned GlyphCount; - unsigned SubstCount; - unsigned *Class; - OTF_SubstLookupRecord *SubstLookupRecord; + unsigned LookupCount; + unsigned *Class; /* [ - 1] */ + OTF_LookupRecord *LookupRecord; /* [] */ }; typedef struct @@ -594,27 +595,27 @@ typedef struct unsigned GlyphCount; unsigned SubstCount; OTF_Coverage *Coverage; - OTF_SubstLookupRecord *SubstLookupRecord; + OTF_LookupRecord *LookupRecord; } OTF_GSUB_Context3; -typedef struct OTF_ChainSubRuleSet OTF_ChainSubRuleSet; +typedef struct OTF_ChainRuleSet OTF_ChainRuleSet; typedef struct { unsigned ChainSubRuleSetCount; - OTF_ChainSubRuleSet *ChainSubRuleSet; + OTF_ChainRuleSet *ChainSubRuleSet; } OTF_GSUB_ChainContext1; -typedef struct OTF_ChainSubRule OTF_ChainSubRule; +typedef struct OTF_ChainRule OTF_ChainRule; -struct OTF_ChainSubRuleSet +struct OTF_ChainRuleSet { OTF_Offset offset; - unsigned ChainSubRuleCount; - OTF_ChainSubRule *ChainSubRule; + unsigned ChainRuleCount; + OTF_ChainRule *ChainRule; }; -struct OTF_ChainSubRule +struct OTF_ChainRule { OTF_Offset offset; unsigned BacktrackGlyphCount; @@ -623,11 +624,11 @@ struct OTF_ChainSubRule OTF_GlyphID *Input; unsigned LookaheadGlyphCount; OTF_GlyphID *LookAhead; - unsigned SubstCount; - OTF_SubstLookupRecord *SubstLookupRecord; + unsigned LookupCount; + OTF_LookupRecord *LookupRecord; }; -typedef struct OTF_ChainSubClassSet OTF_ChainSubClassSet; +typedef struct OTF_ChainClassSet OTF_ChainClassSet; typedef struct { @@ -635,19 +636,19 @@ typedef struct OTF_ClassDef Input; OTF_ClassDef LookAhead; unsigned ChainSubClassSetCnt; - OTF_ChainSubClassSet *ChainSubClassSet; + OTF_ChainClassSet *ChainSubClassSet; } OTF_GSUB_ChainContext2; -typedef struct OTF_ChainSubClassRule OTF_ChainSubClassRule; +typedef struct OTF_ChainClassRule OTF_ChainClassRule; -struct OTF_ChainSubClassSet +struct OTF_ChainClassSet { OTF_Offset offset; - unsigned ChainSubClassRuleCnt; - OTF_ChainSubClassRule *ChainSubClassRule; + unsigned ChainClassRuleCnt; + OTF_ChainClassRule *ChainClassRule; }; -struct OTF_ChainSubClassRule +struct OTF_ChainClassRule { OTF_Offset offset; unsigned BacktrackGlyphCount; @@ -656,8 +657,8 @@ struct OTF_ChainSubClassRule unsigned *Input; unsigned LookaheadGlyphCount; unsigned *LookAhead; - unsigned SubstCount; - OTF_SubstLookupRecord *SubstLookupRecord; + unsigned LookupCount; + OTF_LookupRecord *LookupRecord; }; @@ -670,7 +671,7 @@ typedef struct unsigned LookaheadGlyphCount; OTF_Coverage *LookAhead; unsigned SubstCount; - OTF_SubstLookupRecord *SubstLookupRecord; + OTF_LookupRecord *LookupRecord; } OTF_GSUB_ChainContext3; typedef struct @@ -784,12 +785,15 @@ typedef struct typedef struct { - int dummy; + unsigned ValueFormat; + OTF_ValueRecord Value; } OTF_GPOS_Single1; typedef struct { - int dummy; + unsigned ValueFormat; + unsigned ValueCount; + OTF_ValueRecord *Value; /* [] */ } OTF_GPOS_Single2; typedef struct @@ -826,22 +830,22 @@ typedef struct typedef struct { - OTF_Anchor *BaseAnchor; -} OTF_BaseRecord; + OTF_Anchor *Anchor; +} OTF_AnchorRecord; typedef struct { OTF_Offset offset; - unsigned BaseCount; - OTF_BaseRecord *BaseRecord; -} OTF_BaseArray; + unsigned Count; + OTF_AnchorRecord *AnchorRecord; +} OTF_AnchorArray; typedef struct { OTF_Coverage BaseCoverage; unsigned ClassCount; OTF_MarkArray MarkArray; - OTF_BaseArray BaseArray; + OTF_AnchorArray BaseArray; } OTF_GPOS_MarkBase1; typedef struct @@ -851,37 +855,59 @@ typedef struct typedef struct { - int dummy; + OTF_Coverage Mark2Coverage; + unsigned ClassCount; + OTF_MarkArray Mark1Array; + OTF_AnchorArray Mark2Array; } OTF_GPOS_MarkMark1; + typedef struct { - int dummy; + unsigned PosRuleSetCount; + OTF_RuleSet *PosRuleSet; } OTF_GPOS_Context1; typedef struct { - int dummy; + OTF_ClassDef ClassDef; + unsigned PosClassSetCnt; + OTF_ClassSet *PosClassSet; } OTF_GPOS_Context2; typedef struct { - int dummy; + unsigned GlyphCount; + unsigned PosCount; + OTF_Coverage *Coverage; /* [] */ + OTF_LookupRecord *LookupRecord; /* [] */ } OTF_GPOS_Context3; typedef struct { - int dummy; + unsigned ChainPosRuleSetCount; + OTF_ChainRuleSet *ChainPosRuleSet; } OTF_GPOS_ChainContext1; typedef struct { - int dummy; + OTF_ClassDef Backtrack; + OTF_ClassDef Input; + OTF_ClassDef LookAhead; + unsigned ChainPosClassSetCnt; + OTF_ChainClassSet *ChainPosClassSet; } OTF_GPOS_ChainContext2; typedef struct { - int dummy; + unsigned BacktrackGlyphCount; + OTF_Coverage *Backtrack; + unsigned InputGlyphCount; + OTF_Coverage *Input; + unsigned LookaheadGlyphCount; + OTF_Coverage *LookAhead; + unsigned PosCount; + OTF_LookupRecord *LookupRecord; } OTF_GPOS_ChainContext3; typedef struct diff --git a/src/otfdrive.c b/src/otfdrive.c index 7e3ce4b..336f0d8 100644 --- a/src/otfdrive.c +++ b/src/otfdrive.c @@ -164,6 +164,34 @@ get_feature_index (OTF_LangSys *LangSys, OTF_FeatureList *FeatureList, } static int +match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids) +{ + int i; + + if (gstring->used - gidx < count) + return -1; + for (i = 0; i < count; i++) + if (gstring->glyphs[gidx + i].glyph_id != ids[i]) + return -1; + return 0; +} + +static int +match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx, + int count, unsigned *classes) +{ + int i; + + if (gstring->used - gidx < count) + return -1; + for (i = 0; i < count; i++) + if (get_class_def (class_def, gstring->glyphs[gidx + i].glyph_id) + != classes[i]) + return -1; + return 0; +} + +static int lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GlyphString *gstring, int gidx) { @@ -216,27 +244,31 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, break; case 3: - OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (LookupType not yet supported)"); + if (subtable->Format == 1) + { + OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1; + OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx; + + g->glyph_id = altset->Alternate[0]; + gidx++; + } + else + OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)"); + break; case 4: if (subtable->Format == 1) { OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1; OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx; + OTF_Ligature *lig; int j; for (j = 0; j < ligset->LigatureCount; j++) { - OTF_Ligature *lig = ligset->Ligature + j; - int k; - - if (gstring->used - gidx < lig->CompCount) - continue; - for (k = 1; k < lig->CompCount; k++) - if (gstring->glyphs[gidx + k].glyph_id - != lig->Component[k - 1]) - break; - if (k < lig->CompCount) + lig = ligset->Ligature + j; + if (match_ids (gstring, gidx + 1, + lig->CompCount - 1, lig->Component) < 0) continue; gstring_subst (gstring, gidx, gidx + lig->CompCount, &lig->LigGlyph, 1); @@ -248,6 +280,88 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)"); break; + case 5: + if (subtable->Format == 1) + { + OTF_GSUB_Context1 *context1 = &subtable->u.context1; + OTF_RuleSet *set = context1->SubRuleSet + coverage_idx; + OTF_Rule *rule; + int orig_used; + int j, k; + + for (j = 0; j < set->RuleCount; j++) + { + rule = set->Rule + j; + if (match_ids (gstring, gidx + 1, + rule->GlyphCount - 1, rule->Input) < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gsub (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else if (subtable->Format == 2) + { + OTF_GSUB_Context2 *context2 = &subtable->u.context2; + OTF_ClassSet *set; + OTF_ClassRule *rule; + unsigned class; + int orig_used; + int j, k; + + class = get_class_def (&context2->ClassDef, g->glyph_id); + set = context2->SubClassSet + class; + for (j = 0; j < set->ClassRuleCnt; j++) + { + rule = set->ClassRule + j; + if (match_classes (&context2->ClassDef, + gstring, gidx + 1, + rule->GlyphCount - 1, rule->Class) + < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gsub (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else /* subtable->Format == 3 */ + { + OTF_GSUB_Context3 *context3 = &subtable->u.context3; + int orig_used; + int j, k; + + if (gstring->used - gidx < context3->GlyphCount) + continue; + /* Start from the secoding coverage_idx because the + first one is the same as subtable->Coverage and thus + already tested */ + for (j = 1; j < context3->GlyphCount; j++) + if (get_coverage_index (context3->Coverage + j, + gstring->glyphs[gidx + j].glyph_id) + < 0) + break; + if (j < context3->GlyphCount) + continue; + orig_used = gstring->used; + for (k = 0; k < context3->SubstCount; k++) + lookup_gsub (lookup_list, + context3->LookupRecord[k].LookupListIndex, + gstring, + gidx + context3->LookupRecord[k].SequenceIndex); + gidx += context3->GlyphCount + (gstring->used - orig_used); + } + break; + case 6: if (subtable->Format == 1) OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)"); @@ -274,11 +388,11 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, if (j < context3->BacktrackGlyphCount) continue; - /* Start from the secoding coverage_idx because the - first one is the same as subtable->Coverage and thus + /* Start from the secode coverage_idx because the first + one is the same as subtable->Coverage and thus already tested */ for (j = 1; j < context3->InputGlyphCount; j++) - if (get_coverage_index (context3->Input + j - 1, + if (get_coverage_index (context3->Input + j, gstring->glyphs[gidx + j].glyph_id) < 0) break; @@ -296,9 +410,9 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, orig_used = gstring->used; for (j = 0; j < context3->SubstCount; j++) lookup_gsub (lookup_list, - context3->SubstLookupRecord[j].LookupListIndex, + context3->LookupRecord[j].LookupListIndex, gstring, - gidx + context3->SubstLookupRecord[j].SequenceIndex); + gidx + context3->LookupRecord[j].SequenceIndex); gidx += context3->InputGlyphCount + (gstring->used - orig_used); } break; @@ -421,7 +535,7 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, { OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1; OTF_MarkRecord *mark_record; - OTF_BaseRecord *base_record; + OTF_AnchorRecord *base_record; int coverage_idx_base = get_coverage_index (&mark_base1->BaseCoverage, g[-1].glyph_id); @@ -431,10 +545,10 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id); mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx; base_record - = mark_base1->BaseArray.BaseRecord + coverage_idx_base; + = mark_base1->BaseArray.AnchorRecord + coverage_idx_base; g->f.f4.mark_anchor = &mark_record->MarkAnchor; g->f.f4.base_anchor - = &base_record->BaseAnchor[mark_record->Class]; + = &base_record->Anchor[mark_record->Class]; g->positioning_type = lookup->LookupType; break; } @@ -442,7 +556,47 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); break; + case 5: + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + break; + case 6: + if (gidx < 1) + continue; + if (subtable->Format == 1) + { + OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1; + OTF_MarkRecord *mark1_record; + OTF_AnchorRecord *mark2_record; + int coverage_idx_base + = get_coverage_index (&mark_mark1->Mark2Coverage, + g[-1].glyph_id); + + if (coverage_idx_base < 0) + continue; + printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id); + mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx; + mark2_record + = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base; + g->f.f6.mark1_anchor = &mark1_record->MarkAnchor; + g->f.f6.mark2_anchor + = &mark2_record->Anchor[mark1_record->Class]; + g->positioning_type = lookup->LookupType; + break; + } + else + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + break; + + case 7: + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + break; + + case 8: + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + break; + + case 9: OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); break; diff --git a/src/otferror.c b/src/otferror.c index 20db616..aed9623 100644 --- a/src/otferror.c +++ b/src/otferror.c @@ -12,10 +12,10 @@ static char *error_string[] = "No error", "Memory shortage", "File error", - "Invalid table" - "CMAP drive" - "GDEF drive" - "GSUB drive" + "Invalid table", + "CMAP drive", + "GDEF drive", + "GSUB drive", "GPOS drive" }; diff --git a/src/otfopen.c b/src/otfopen.c index d59b0ae..648429f 100644 --- a/src/otfopen.c +++ b/src/otfopen.c @@ -564,21 +564,27 @@ read_lookup_list (OTF *otf, OTF_Stream *stream, long offset, } +/* Read Glyph-IDs from STREAM. Allocate memory for IDS, and store the + Glyph-IDs there. If COUNT is negative, read the number of + Glyphs-IDs at first. MINUS if nozero is how few the actual + Glyph-IDs are in STREAM than COUNT. */ + static int -read_glyph_ids (OTF *otf, OTF_Stream *stream, OTF_GlyphID **ids, int minus) +read_glyph_ids (OTF *otf, OTF_Stream *stream, OTF_GlyphID **ids, + int minus, int count) { char *errfmt = "GlyphID List%s"; int errret = -1; - unsigned count; int i; - READ_UINT16 (stream, count); + if (count < 0) + READ_UINT16 (stream, count); if (! count) return 0; OTF_MALLOC (*ids, count, ""); for (i = 0; i < count + minus; i++) READ_GLYPHID (stream, (*ids)[i]); - return (int) count; + return count; } static unsigned @@ -617,7 +623,7 @@ read_coverage (OTF *otf, OTF_Stream *stream, long offset, SEEK_STREAM (stream, offset + coverage->offset); READ_UINT16 (stream, coverage->CoverageFormat); if (coverage->CoverageFormat == 1) - count = read_glyph_ids (otf, stream, &coverage->table.GlyphArray, 0); + count = read_glyph_ids (otf, stream, &coverage->table.GlyphArray, 0, -1); else if (coverage->CoverageFormat == 2) count = read_range_records (otf, stream, &coverage->table.RangeRecord); else @@ -629,16 +635,20 @@ read_coverage (OTF *otf, OTF_Stream *stream, long offset, return 0; } +/* Read list of Coverages from STREAM. Allocate memory for COVERAGE, + and store the Coverages there. If COUNT is negative, read the + number of Coverages at first. */ + static int read_coverage_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_Coverage **coverage) + OTF_Coverage **coverage, int count) { char *errfmt = "Coverage List%s"; int errret = -1; - int count; int i; - READ_UINT16 (stream, count); + if (count < 0) + READ_UINT16 (stream, count); if (! count) return 0; OTF_MALLOC (*coverage, count, ""); @@ -663,7 +673,7 @@ read_class_def_without_offset (OTF *otf, OTF_Stream *stream, READ_GLYPHID (stream, class->f.f1.StartGlyph); class->f.f1.GlyphCount = (read_glyph_ids - (otf, stream, (OTF_GlyphID **) &class->f.f1.ClassValueArray, 0)); + (otf, stream, (OTF_GlyphID **) &class->f.f1.ClassValueArray, 0, -1)); if (! class->f.f1.GlyphCount) OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); } @@ -689,6 +699,8 @@ read_class_def (OTF *otf, OTF_Stream *stream, long offset, OTF_ClassDef *class) OTF_StreamState state; READ_OFFSET (stream, class->offset); + if (! class->offset) + return 0; SAVE_STREAM (stream, state); SEEK_STREAM (stream, offset + class->offset); READ_UINT16 (stream, class->ClassFormat); @@ -696,16 +708,18 @@ read_class_def (OTF *otf, OTF_Stream *stream, long offset, OTF_ClassDef *class) { READ_GLYPHID (stream, class->f.f1.StartGlyph); class->f.f1.GlyphCount - = (read_glyph_ids - (otf, stream, (OTF_GlyphID **) &class->f.f1.ClassValueArray, 0)); + = read_glyph_ids (otf, stream, + (OTF_GlyphID **) &class->f.f1.ClassValueArray, + 0, -1); if (! class->f.f1.GlyphCount) return -1; } else if (class->ClassFormat == 2) { class->f.f2.ClassRangeCount - = (read_range_records - (otf, stream, (OTF_RangeRecord **) &class->f.f2.ClassRangeRecord)); + = read_range_records (otf, stream, + (OTF_RangeRecord **) + &class->f.f2.ClassRangeRecord); if (! class->f.f2.ClassRangeCount) return -1; } @@ -775,139 +789,176 @@ read_device_table (OTF *otf, OTF_Stream *stream, long offset, return 0; } - -/* GSUB */ - -static void * -read_gsub_table (OTF *otf, OTF_Stream *stream) +static unsigned +read_lookup_record_list (OTF *otf, OTF_Stream *stream, + OTF_LookupRecord **record, int count) { - char *errfmt = "GSUB%s"; - void *errret = NULL; - OTF_GSUB *gsub; + char *errfmt = "LookupRecord%s"; + unsigned errret = 0; + int i; - OTF_CALLOC (gsub, 1, ""); - READ_FIXED (stream, gsub->Version); - READ_OFFSET (stream, gsub->ScriptList.offset); - READ_OFFSET (stream, gsub->FeatureList.offset); - READ_OFFSET (stream, gsub->LookupList.offset); - - if (read_script_list (otf, stream, gsub->ScriptList.offset, - &gsub->ScriptList) < 0 - || read_feature_list (otf, stream, gsub->FeatureList.offset, - &gsub->FeatureList) < 0 - || read_lookup_list (otf, stream, gsub->LookupList.offset, - &gsub->LookupList, 1) < 0) - return NULL; - return gsub; + if (count < 0) + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*record, count, ""); + for (i = 0; i < count; i++) + { + READ_UINT16 (stream, (*record)[i].SequenceIndex); + READ_UINT16 (stream, (*record)[i].LookupListIndex); + } + return count; } static unsigned -read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq) +read_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule) { - char *errfmt = "Sequence%s"; + char *errfmt = "List of Rule%s"; unsigned errret = 0; + OTF_StreamState state; unsigned count; int i; READ_UINT16 (stream, count); - OTF_MALLOC (*seq, count, ""); if (! count) OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*rule, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*seq)[i].offset); + { + READ_OFFSET (stream, (*rule)[i].offset); + if (! (*rule)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } + SAVE_STREAM (stream, state); for (i = 0; i < count; i++) { - SEEK_STREAM (stream, offset + (*seq)[i].offset); - (*seq)[i].GlyphCount = read_glyph_ids (otf, stream, - &(*seq)[i].Substitute, 0); - if (! (*seq)[i].GlyphCount) - return 0; + SEEK_STREAM (stream, offset + (*rule)[i].offset); + READ_UINT16 (stream, (*rule)[i].GlyphCount); + if ((*rule)[i].GlyphCount == 0) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_UINT16 (stream, (*rule)[i].LookupCount); + if (read_glyph_ids (otf, stream, &(*rule)[i].Input, 0, + (*rule)[i].GlyphCount) < 0) + return errret; + if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord, + (*rule)[i].LookupCount) == 0) + return errret; } + RESTORE_STREAM (stream, state); return count; } -static int -read_ligature (OTF *otf, OTF_Stream *stream, long offset, - OTF_Ligature **ligature) + +static unsigned +read_rule_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_RuleSet **set) { - char *errfmt = "Ligature%s"; - int errret = -1; - int count; + char *errfmt = "List of RuleSet%s"; + unsigned errret = 0; + OTF_StreamState state; + unsigned count; int i; READ_UINT16 (stream, count); if (! count) - return 0; - OTF_MALLOC (*ligature, count, ""); + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*set, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*ligature)[i].offset); + { + READ_OFFSET (stream, (*set)[i].offset); + if (! (*set)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } + SAVE_STREAM (stream, state); for (i = 0; i < count; i++) { - SEEK_STREAM (stream, offset + (*ligature)[i].offset); - READ_GLYPHID (stream, (*ligature)[i].LigGlyph); - (*ligature)[i].CompCount - = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1); - if (! (*ligature)[i].CompCount) - return -1; + SEEK_STREAM (stream, offset + (*set)[i].offset); + (*set)[i].RuleCount + = read_rule_list (otf, stream, offset + (*set)[i].offset, + &(*set)[i].Rule); + if (! (*set)[i].RuleCount) + return errret; } + RESTORE_STREAM (stream, state); return count; } -static int -read_ligature_set (OTF *otf, OTF_Stream *stream, long offset, - OTF_LigatureSet **ligset) +static unsigned +read_class_rule_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ClassRule **rule) { - char *errfmt = "LigatureSet%s"; - int errret = -1; - int count; + char *errfmt = "ClassRule%s"; + unsigned errret = 0; + OTF_StreamState state; + unsigned count; int i; READ_UINT16 (stream, count); if (! count) - return 0; - OTF_MALLOC (*ligset, count, ""); + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*rule, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*ligset)[i].offset); + { + READ_OFFSET (stream, (*rule)[i].offset); + if (! (*rule)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } + SAVE_STREAM (stream, state); for (i = 0; i < count; i++) { - int lig_count; - - SEEK_STREAM (stream, offset + (*ligset)[i].offset); - lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset, - &(*ligset)[i].Ligature); - if (lig_count < 0) - return -1; - (*ligset)[i].LigatureCount = (unsigned) lig_count; + SEEK_STREAM (stream, offset + (*rule)[i].offset); + READ_USHORT (stream, (*rule)[i].GlyphCount); + if (! (*rule)[i].GlyphCount) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_USHORT (stream, (*rule)[i].LookupCount); + if (read_glyph_ids (otf, stream, (OTF_GlyphID **) &(*rule)[i].Class, + 0, (*rule)[i].GlyphCount - 1) < 0) + return errret; + if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord, + (*rule)[i].LookupCount) == 0) + return errret; } + RESTORE_STREAM (stream, state); return count; } static unsigned -read_subst_lookup_record (OTF *otf, OTF_Stream *stream, - OTF_SubstLookupRecord **record) +read_class_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ClassSet **set) { - char *errfmt = "SubstLookupRecord%s"; + char *errfmt = "ClassSet%s"; unsigned errret = 0; + OTF_StreamState state; unsigned count; int i; READ_UINT16 (stream, count); if (! count) OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*record, count, ""); + OTF_MALLOC (*set, count, ""); for (i = 0; i < count; i++) - { - READ_UINT16 (stream, (*record)[i].SequenceIndex); - READ_UINT16 (stream, (*record)[i].LookupListIndex); - } + /* Offset can be zero. */ + READ_OFFSET (stream, (*set)[i].offset); + SAVE_STREAM (stream, state); + for (i = 0; i < count; i++) + if ((*set)[i].offset) + { + SEEK_STREAM (stream, offset + (*set)[i].offset); + (*set)[i].ClassRuleCnt + = read_class_rule_list (otf, stream, offset + (*set)[i].offset, + &(*set)[i].ClassRule); + if (! (*set)[i].ClassRuleCnt) + return errret; + } + RESTORE_STREAM (stream, state); return count; } static unsigned -read_chain_subrule (OTF *otf, OTF_Stream *stream, long offset, - OTF_ChainSubRule **rule) +read_chain_rule_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ChainRule **rule) { - char *errfmt = "ChainSubRule%s"; + char *errfmt = "ChainRule%s"; unsigned errret = 0; unsigned count; int i; @@ -922,32 +973,30 @@ read_chain_subrule (OTF *otf, OTF_Stream *stream, long offset, { SEEK_STREAM (stream, offset + (*rule)[i].offset); (*rule)[i].BacktrackGlyphCount - = read_glyph_ids (otf, stream, &(*rule)[i].Backtrack, 0); - if (! (*rule)[i].BacktrackGlyphCount) - return 0; + = read_glyph_ids (otf, stream, &(*rule)[i].Backtrack, 0, -1); (*rule)[i].InputGlyphCount - = read_glyph_ids (otf, stream, &(*rule)[i].Input, -1); + = read_glyph_ids (otf, stream, &(*rule)[i].Input, -1, -1); if (! (*rule)[i].InputGlyphCount) - return 0; + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); (*rule)[i].LookaheadGlyphCount - = read_glyph_ids (otf, stream, &(*rule)[i].LookAhead, 0); - if (! (*rule)[i].LookaheadGlyphCount) - return 0; - (*rule)[i].SubstCount - = read_subst_lookup_record (otf, stream, &(*rule)[i].SubstLookupRecord); - if (! (*rule)[i].SubstCount) - return 0; + = read_glyph_ids (otf, stream, &(*rule)[i].LookAhead, 0, -1); + (*rule)[i].LookupCount + = read_lookup_record_list (otf, stream, + &(*rule)[i].LookupRecord, -1); + if (! (*rule)[i].LookupCount) + return errret; } return count; } static unsigned -read_chain_subrule_set (OTF *otf, OTF_Stream *stream, long offset, - OTF_ChainSubRuleSet **set) +read_chain_rule_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ChainRuleSet **set) { - char *errfmt = "ChainSubRuleSet%s"; + char *errfmt = "ChainRuleSet%s"; unsigned errret = 0; + OTF_StreamState state; unsigned count; int i; @@ -956,24 +1005,30 @@ read_chain_subrule_set (OTF *otf, OTF_Stream *stream, long offset, OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); OTF_MALLOC (*set, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*set)[i].offset); + { + READ_OFFSET (stream, (*set)[i].offset); + if (! (*set)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } + SAVE_STREAM (stream, state); for (i = 0; i < count; i++) { SEEK_STREAM (stream, offset + (*set)[i].offset); - (*set)[i].ChainSubRuleCount - = read_chain_subrule (otf, stream, offset + (*set)[i].offset, - &(*set)[i].ChainSubRule); - if (! (*set)[i].ChainSubRuleCount) - return 0; + (*set)[i].ChainRuleCount + = read_chain_rule_list (otf, stream, offset + (*set)[i].offset, + &(*set)[i].ChainRule); + if (! (*set)[i].ChainRuleCount) + return errret; } + RESTORE_STREAM (stream, state); return count; } static unsigned -read_chain_subclass_rule (OTF *otf, OTF_Stream *stream, long offset, - OTF_ChainSubClassRule **rule) +read_chain_class_rule_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ChainClassRule **rule) { - char *errfmt = "ChainSubClassRule%s"; + char *errfmt = "ChainClassRule%s"; unsigned errret = 0; unsigned count; int i; @@ -983,37 +1038,41 @@ read_chain_subclass_rule (OTF *otf, OTF_Stream *stream, long offset, OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); OTF_MALLOC (*rule, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*rule)[i].offset); + { + READ_OFFSET (stream, (*rule)[i].offset); + if (! (*rule)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } for (i = 0; i < count; i++) { SEEK_STREAM (stream, offset + (*rule)[i].offset); (*rule)[i].BacktrackGlyphCount = read_glyph_ids (otf, stream, - (OTF_GlyphID **) &(*rule)[i].Backtrack, 0); - if (! (*rule)[i].BacktrackGlyphCount) - return 0; + (OTF_GlyphID **) &(*rule)[i].Backtrack, 0, -1); (*rule)[i].InputGlyphCount - = read_glyph_ids (otf, stream, (OTF_GlyphID **) &(*rule)[i].Input, -1); + = read_glyph_ids (otf, stream, + (OTF_GlyphID **) &(*rule)[i].Input, -1, -1); if (! (*rule)[i].InputGlyphCount) - return 0; + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); (*rule)[i].LookaheadGlyphCount - = read_glyph_ids (otf, stream, (OTF_GlyphID **) &(*rule)[i].LookAhead, 0); - if (! (*rule)[i].LookaheadGlyphCount) - return 0; - (*rule)[i].SubstCount - = read_subst_lookup_record (otf, stream, &(*rule)[i].SubstLookupRecord); - if (! (*rule)[i].SubstCount) - return 0; + = read_glyph_ids (otf, stream, + (OTF_GlyphID **) &(*rule)[i].LookAhead, 0, -1); + (*rule)[i].LookupCount + = read_lookup_record_list (otf, stream, + &(*rule)[i].LookupRecord, -1); + if (! (*rule)[i].LookupCount) + return errret; } return count; } static unsigned -read_chain_subclass_set (OTF *otf, OTF_Stream *stream, long offset, - OTF_ChainSubClassSet **set) +read_chain_class_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ChainClassSet **set) { - char *errfmt = "ChainSubClassSet%s"; + char *errfmt = "ChainClassSet%s"; unsigned errret = 0; + OTF_StreamState state; unsigned count; int i; @@ -1022,30 +1081,169 @@ read_chain_subclass_set (OTF *otf, OTF_Stream *stream, long offset, OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); OTF_MALLOC (*set, count, ""); for (i = 0; i < count; i++) + /* Offset may be zero. */ READ_OFFSET (stream, (*set)[i].offset); + SAVE_STREAM (stream, state); + for (i = 0; i < count; i++) + if ((*set)[i].offset) + { + SEEK_STREAM (stream, offset + (*set)[i].offset); + (*set)[i].ChainClassRuleCnt + = read_chain_class_rule_list (otf, stream, offset + (*set)[i].offset, + &(*set)[i].ChainClassRule); + if (! (*set)[i].ChainClassRuleCnt) + return errret; + } + RESTORE_STREAM (stream, state); + return count; +} + + +/* GSUB */ + +static void * +read_gsub_table (OTF *otf, OTF_Stream *stream) +{ + char *errfmt = "GSUB%s"; + void *errret = NULL; + OTF_GSUB *gsub; + + OTF_CALLOC (gsub, 1, ""); + READ_FIXED (stream, gsub->Version); + READ_OFFSET (stream, gsub->ScriptList.offset); + READ_OFFSET (stream, gsub->FeatureList.offset); + READ_OFFSET (stream, gsub->LookupList.offset); + + if (read_script_list (otf, stream, gsub->ScriptList.offset, + &gsub->ScriptList) < 0 + || read_feature_list (otf, stream, gsub->FeatureList.offset, + &gsub->FeatureList) < 0 + || read_lookup_list (otf, stream, gsub->LookupList.offset, + &gsub->LookupList, 1) < 0) + return NULL; + return gsub; +} + +static unsigned +read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq) +{ + char *errfmt = "Sequence%s"; + unsigned errret = 0; + unsigned count; + int i; + + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*seq, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*seq)[i].offset); for (i = 0; i < count; i++) { - SEEK_STREAM (stream, offset + (*set)[i].offset); - (*set)[i].ChainSubClassRuleCnt - = read_chain_subclass_rule (otf, stream, offset + (*set)[i].offset, - &(*set)[i].ChainSubClassRule); - if (! (*set)[i].ChainSubClassRuleCnt) + SEEK_STREAM (stream, offset + (*seq)[i].offset); + (*seq)[i].GlyphCount = read_glyph_ids (otf, stream, + &(*seq)[i].Substitute, 0, -1); + if (! (*seq)[i].GlyphCount) return 0; } return count; } +static int +read_ligature (OTF *otf, OTF_Stream *stream, long offset, + OTF_Ligature **ligature) +{ + char *errfmt = "Ligature%s"; + int errret = -1; + int count; + int i; + + READ_UINT16 (stream, count); + if (! count) + return 0; + OTF_MALLOC (*ligature, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*ligature)[i].offset); + for (i = 0; i < count; i++) + { + SEEK_STREAM (stream, offset + (*ligature)[i].offset); + READ_GLYPHID (stream, (*ligature)[i].LigGlyph); + (*ligature)[i].CompCount + = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1, -1); + if (! (*ligature)[i].CompCount) + return -1; + } + return count; +} + +static unsigned +read_ligature_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_LigatureSet **ligset) +{ + char *errfmt = "LigatureSet%s"; + int errret = 0; + int count; + int i; + + READ_UINT16 (stream, count); + if (! count) + return errret; + OTF_MALLOC (*ligset, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*ligset)[i].offset); + for (i = 0; i < count; i++) + { + int lig_count; + + SEEK_STREAM (stream, offset + (*ligset)[i].offset); + lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset, + &(*ligset)[i].Ligature); + if (lig_count < 0) + return errret; + (*ligset)[i].LigatureCount = (unsigned) lig_count; + } + return count; +} + +static unsigned +read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_AlternateSet **altset) +{ + char *errfmt = "AlternateSet%s"; + int errret = -1; + unsigned count; + int i; + + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*altset, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*altset)[i].offset); + for (i = 0; i < count; i++) + { + int alt_count; + + SEEK_STREAM (stream, offset + (*altset)[i].offset); + alt_count = read_glyph_ids (otf, stream, &(*altset)[i].Alternate, 0, -1); + if (alt_count < 0) + return errret; + (*altset)[i].GlyphCount = (unsigned) alt_count; + } + return count; +} static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset, unsigned type, OTF_LookupSubTableGSUB *subtable) { - char *errfmt = "GSUB LookupSubTable%s"; + char errfmt[256]; int errret = -1; int count; SEEK_STREAM (stream, offset); READ_UINT16 (stream, subtable->Format); + sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format); switch (type) { case 1: @@ -1061,7 +1259,7 @@ read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset, return -1; subtable->u.single2.GlyphCount = read_glyph_ids (otf, stream, &subtable->u.single2.Substitute, - 0); + 0, -1); if (! subtable->u.single2.GlyphCount) return -1; } @@ -1082,80 +1280,129 @@ read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset, break; case 3: + if (subtable->Format == 1) + { + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + subtable->u.alternate1.AlternateSetCount + = read_alternate_set_list (otf, stream, offset, + &subtable->u.alternate1.AlternateSet); + if (! subtable->u.alternate1.AlternateSetCount) + return -1; + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; case 4: if (subtable->Format == 1) { - read_coverage (otf, stream, offset, &subtable->Coverage); - count = (read_ligature_set - (otf, stream, offset, - &subtable->u.ligature1.LigatureSet)); - if (count < 0) + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + subtable->u.ligature1.LigSetCount + = read_ligature_set_list (otf, stream, offset, + &subtable->u.ligature1.LigatureSet); + if (! subtable->u.ligature1.LigSetCount) return -1; - subtable->u.ligature1.LigSetCount = (unsigned) count; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; + case 5: + if (subtable->Format == 1) + { + OTF_GSUB_Context1 *context1 = &subtable->u.context1; + + read_coverage (otf, stream, offset, &subtable->Coverage); + context1->SubRuleSetCount + = read_rule_set_list (otf, stream, offset, &context1->SubRuleSet); + } + else if (subtable->Format == 2) + { + OTF_GSUB_Context2 *context2 = &subtable->u.context2; + + read_coverage (otf, stream, offset, &subtable->Coverage); + read_class_def (otf, stream, offset, &context2->ClassDef); + context2->SubClassSetCnt + = read_class_set_list (otf, stream, offset, &context2->SubClassSet); + } + else if (subtable->Format == 3) + { + OTF_GSUB_Context3 *context3 = &subtable->u.context3; + + READ_USHORT (stream, context3->GlyphCount); + if (context3->GlyphCount < 0) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_USHORT (stream, context3->SubstCount); + if (read_coverage_list (otf, stream, offset, + &context3->Coverage, + context3->GlyphCount) < 0) + return -1; + if (read_lookup_record_list (otf, stream, + &context3->LookupRecord, + context3->SubstCount) < 0) + return -1; + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + case 6: if (subtable->Format == 1) { + OTF_GSUB_ChainContext1 *chain_context1 = &subtable->u.chain_context1; + read_coverage (otf, stream, offset, &subtable->Coverage); - subtable->u.chain_context1.ChainSubRuleSetCount - = (read_chain_subrule_set - (otf, stream, offset, - &subtable->u.chain_context1.ChainSubRuleSet)); + chain_context1->ChainSubRuleSetCount + = read_chain_rule_set_list (otf, stream, offset, + &chain_context1->ChainSubRuleSet); } else if (subtable->Format == 2) { + OTF_GSUB_ChainContext2 *chain_context2 = &subtable->u.chain_context2; + read_coverage (otf, stream, offset, &subtable->Coverage); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.Backtrack); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.Input); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.LookAhead); - subtable->u.chain_context2.ChainSubClassSetCnt - = (read_chain_subclass_set - (otf, stream, offset, - &subtable->u.chain_context2.ChainSubClassSet)); + read_class_def (otf, stream, offset, &chain_context2->Backtrack); + read_class_def (otf, stream, offset, &chain_context2->Input); + read_class_def (otf, stream, offset, &chain_context2->LookAhead); + chain_context2->ChainSubClassSetCnt + = read_chain_class_set_list (otf, stream, offset, + &chain_context2->ChainSubClassSet); } else if (subtable->Format == 3) { - count = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.Backtrack)); + OTF_GSUB_ChainContext3 *chain_context3 = &subtable->u.chain_context3; + + count = read_coverage_list (otf, stream, offset, + &chain_context3->Backtrack, -1); if (count < 0) return -1; - subtable->u.chain_context3.BacktrackGlyphCount - = (unsigned) count; - count = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.Input)); + chain_context3->BacktrackGlyphCount = (unsigned) count; + count = read_coverage_list (otf, stream, offset, + &chain_context3->Input, -1); if (count <= 0) return -1; - subtable->u.chain_context3.InputGlyphCount - = (unsigned) count; - subtable->Coverage = subtable->u.chain_context3.Input[0]; - count = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.LookAhead)); - subtable->u.chain_context3.LookaheadGlyphCount - = (unsigned) count; - subtable->u.chain_context3.SubstCount - = (read_subst_lookup_record - (otf, stream, - &subtable->u.chain_context3.SubstLookupRecord)); + chain_context3->InputGlyphCount = (unsigned) count; + subtable->Coverage = chain_context3->Input[0]; + count = read_coverage_list (otf, stream, offset, + &chain_context3->LookAhead, -1); + chain_context3->LookaheadGlyphCount = (unsigned) count; + chain_context3->SubstCount + = read_lookup_record_list (otf, stream, + &chain_context3->LookupRecord, -1); } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; + case 7: + case 8: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; default: - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); } return 0; } @@ -1286,10 +1533,10 @@ read_mark_array (OTF *otf, OTF_Stream *stream, long offset, } static int -read_base_array (OTF *otf, OTF_Stream *stream, long offset, - unsigned ClassCount, OTF_BaseArray *array) +read_anchor_array (OTF *otf, OTF_Stream *stream, long offset, + unsigned ClassCount, OTF_AnchorArray *array) { - char *errfmt = "BaseArray%s"; + char *errfmt = "AnchorArray%s"; int errret = -1; OTF_StreamState state; int i, j; @@ -1297,19 +1544,19 @@ read_base_array (OTF *otf, OTF_Stream *stream, long offset, READ_OFFSET (stream, array->offset); SAVE_STREAM (stream, state); SEEK_STREAM (stream, offset + array->offset); - READ_UINT16 (stream, array->BaseCount); - OTF_MALLOC (array->BaseRecord, array->BaseCount, ""); - for (i = 0; i < array->BaseCount; i++) + READ_UINT16 (stream, array->Count); + OTF_MALLOC (array->AnchorRecord, array->Count, ""); + for (i = 0; i < array->Count; i++) { - OTF_MALLOC (array->BaseRecord[i].BaseAnchor, ClassCount, - " (BaseRecord)"); + OTF_MALLOC (array->AnchorRecord[i].Anchor, ClassCount, + " (AnchorRecord)"); for (j = 0; j < ClassCount; j++) - READ_OFFSET (stream, array->BaseRecord[i].BaseAnchor[j].offset); + READ_OFFSET (stream, array->AnchorRecord[i].Anchor[j].offset); } - for (i = 0; i < array->BaseCount; i++) + for (i = 0; i < array->Count; i++) for (j = 0; j < ClassCount; j++) if (read_anchor (otf, stream, offset + array->offset, - &array->BaseRecord[i].BaseAnchor[j]) < 0) + &array->AnchorRecord[i].Anchor[j]) < 0) return -1; RESTORE_STREAM (stream, state); return 0; @@ -1342,42 +1589,48 @@ read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset, return rec; } - static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, long offset, unsigned type, OTF_LookupSubTableGPOS *subtable) { - char *errfmt = "GPOS LookupSubTable%s"; + char errfmt[256]; int errret = -1; + int count; SEEK_STREAM (stream, offset); READ_UINT16 (stream, subtable->Format); + sprintf (errfmt, "GPOS Lookup %d-%d%%s", type, subtable->Format); switch (type) { case 1: -#if 0 if (subtable->Format == 1) { - read_coverage (otf, stream, offset, &subtable->Coverage); - subtable->u.single1.DeltaGlyphID = READ_INT16 (stream); + READ_UINT16 (stream, subtable->u.single1.ValueFormat); + read_value_record (otf, stream, offset, + subtable->u.single1.ValueFormat, + &subtable->u.single1.Value); } else if (subtable->Format == 2) { - read_coverage (otf, stream, offset, &subtable->Coverage); - subtable->u.single2.GlyphCount - = read_glyph_ids (otf, stream, - &subtable->u.single2.Substitute, 0); + OTF_GPOS_Single2 *single2 = &subtable->u.single2; + int i; + + READ_UINT16 (stream, single2->ValueFormat); + READ_UINT16 (stream, single2->ValueCount); + OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)"); + for (i = 0; i < single2->ValueCount; i++) + read_value_record (otf, stream, offset, single2->ValueFormat, + single2->Value + i); } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); -#endif break; case 2: if (subtable->Format == 1) { - read_coverage (otf, stream, offset, &subtable->Coverage); + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); } else if (subtable->Format == 2) { @@ -1402,6 +1655,10 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; + case 3: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; + case 4: if (subtable->Format == 1) { @@ -1411,65 +1668,129 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); read_mark_array (otf, stream, offset, &subtable->u.mark_base1.MarkArray); - read_base_array (otf, stream, offset, - subtable->u.mark_base1.ClassCount, - &subtable->u.mark_base1.BaseArray); + read_anchor_array (otf, stream, offset, + subtable->u.mark_base1.ClassCount, + &subtable->u.mark_base1.BaseArray); } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; + case 5: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; + case 6: -#if 0 if (subtable->Format == 1) { + read_coverage (otf, stream, offset, &subtable->Coverage); read_coverage (otf, stream, offset, - &subtable->u.chain_context1.Coverage); - subtable->u.chain_context1.ChainSubRuleSetCount - = (read_chain_subrule_set - (otf, stream, offset, - &subtable->u.chain_context1.ChainSubRuleSet)); + &subtable->u.mark_mark1.Mark2Coverage); + READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); + read_mark_array (otf, stream, offset, + &subtable->u.mark_mark1.Mark1Array); + read_anchor_array (otf, stream, offset, + subtable->u.mark_mark1.ClassCount, + &subtable->u.mark_mark1.Mark2Array); + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 7: + if (subtable->Format == 1) + { + OTF_GPOS_Context1 *context1 = &subtable->u.context1; + + read_coverage (otf, stream, offset, &subtable->Coverage); + context1->PosRuleSetCount + = read_rule_set_list (otf, stream, offset, &context1->PosRuleSet); } else if (subtable->Format == 2) { - read_coverage (otf, stream, offset, - &subtable->u.chain_context2.Coverage); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.Backtrack); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.Input); - read_class_def (otf, stream, offset, - &subtable->u.chain_context2.LookAhead); - subtable->u.chain_context2.ChainSubClassSetCnt - = (read_chain_subclass_set - (otf, stream, offset, - &subtable->u.chain_context2.ChainSubClassSet)); + OTF_GPOS_Context2 *context2 = &subtable->u.context2; + + read_coverage (otf, stream, offset, &subtable->Coverage); + read_class_def (otf, stream, offset, &context2->ClassDef); + context2->PosClassSetCnt + = read_class_set_list (otf, stream, offset, &context2->PosClassSet); + + } + else if (subtable->Format == 3) + { + OTF_GPOS_Context3 *context3 = &subtable->u.context3; + + READ_USHORT (stream, context3->GlyphCount); + if (context3->GlyphCount < 0) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_USHORT (stream, context3->PosCount); + if (read_coverage_list (otf, stream, offset, + &context3->Coverage, + context3->GlyphCount) < 0) + return -1; + if (read_lookup_record_list (otf, stream, + &context3->LookupRecord, + context3->PosCount) < 0) + return -1; + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 8: + if (subtable->Format == 1) + { + OTF_GPOS_ChainContext1 *chain_context1 = &subtable->u.chain_context1; + + read_coverage (otf, stream, offset, &subtable->Coverage); + chain_context1->ChainPosRuleSetCount + = read_chain_rule_set_list (otf, stream, offset, + &chain_context1->ChainPosRuleSet); + } + else if (subtable->Format == 2) + { + OTF_GPOS_ChainContext2 *chain_context2 = &subtable->u.chain_context2; + + read_coverage (otf, stream, offset, &subtable->Coverage); + read_class_def (otf, stream, offset, &chain_context2->Backtrack); + read_class_def (otf, stream, offset, &chain_context2->Input); + read_class_def (otf, stream, offset, &chain_context2->LookAhead); + chain_context2->ChainPosClassSetCnt + = read_chain_class_set_list (otf, stream, offset, + &chain_context2->ChainPosClassSet); } else if (subtable->Format == 3) { - subtable->u.chain_context3.BacktrackGlyphCount - = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.Backtrack)); - subtable->u.chain_context3.InputGlyphCount - = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.Input)); - subtable->u.chain_context3.LookaheadGlyphCount - = (read_coverage_list - (otf, stream, offset, - &subtable->u.chain_context3.LookAhead)); - subtable->u.chain_context3.SubstCount - = (read_subst_lookup_record - (otf, stream, - &subtable->u.chain_context3.SubstLookupRecord)); + OTF_GPOS_ChainContext3 *chain_context3 = &subtable->u.chain_context3; + + count = read_coverage_list (otf, stream, offset, + &chain_context3->Backtrack, -1); + if (count < 0) + return -1; + chain_context3->BacktrackGlyphCount = (unsigned) count; + count = read_coverage_list (otf, stream, offset, + &chain_context3->Input, -1); + if (count <= 0) + return -1; + chain_context3->InputGlyphCount = (unsigned) count; + subtable->Coverage = chain_context3->Input[0]; + count = read_coverage_list (otf, stream, offset, + &chain_context3->LookAhead, -1); + chain_context3->LookaheadGlyphCount = (unsigned) count; + chain_context3->PosCount + = read_lookup_record_list (otf, stream, + &chain_context3->LookupRecord, -1); } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); -#endif + break; + + case 9: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; default: - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); } return 0; } @@ -1524,7 +1845,7 @@ read_jstf_table (OTF_Stream *stream, long offset) return jstf; } -#endif +#endif /* 0 */ /* GDEF */ static int @@ -1966,14 +2287,14 @@ OTF_close (OTF *otf) int OTF_get_table (OTF *otf, char *name) { - char *errfmt = "OTF Table Read"; + char *errfmt = "OTF Table Read%s"; int errret = -1; OTF_InternalData *internal_data = otf->internal_data; OTF_TableInfo *table_info; OTF_Tag tag = OTF_tag (name); if (! tag) - OTF_ERROR (OTF_ERROR_TABLE, " (unknown)"); + OTF_ERROR (OTF_ERROR_TABLE, " (invalid table name)"); if (tag == OTF_tag ("head")) table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD; @@ -1988,12 +2309,13 @@ OTF_get_table (OTF *otf, char *name) else if (tag == OTF_tag ("GPOS")) table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS; else - OTF_ERROR (OTF_ERROR_TABLE, " (unsupported)"); + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported table name)"); if (*table_info->address) + /* Already read. */ return 0; if (! table_info->stream) - OTF_ERROR (OTF_ERROR_TABLE, " (not found)"); + OTF_ERROR (OTF_ERROR_TABLE, " (table not found)"); if (! table_info->reader) OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)"); @@ -2003,7 +2325,7 @@ OTF_get_table (OTF *otf, char *name) if (! *table_info->address) { table_info->reader = NULL; - OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)"); + return errret; } return 0;