+ int i, j;
+
+ if (read_coverage (otf, stream, offset, &list->Coverage) < 0)
+ return -1;
+ READ_UINT16 (stream, list->LigGlyphCount);
+ OTF_MALLOC (list->LigGlyph, list->LigGlyphCount, "");
+ for (i = 0; i < list->LigGlyphCount; i++)
+ READ_OFFSET (stream, list->LigGlyph[i].offset);
+ for (i = 0; i < list->LigGlyphCount; i++)
+ {
+ int count;
+
+ SEEK_STREAM (stream, offset + list->LigGlyph[i].offset);
+ READ_UINT16 (stream, count);
+ list->LigGlyph[i].CaretCount = count;
+ OTF_MALLOC (list->LigGlyph[i].CaretValue, count, " (CaretValue)");
+ for (j = 0; j < count; j++)
+ READ_OFFSET (stream, list->LigGlyph[i].CaretValue[j].offset);
+ for (j = 0; j < count; j++)
+ if (read_caret_value (otf, stream, offset + list->LigGlyph[i].offset,
+ &list->LigGlyph[i].CaretValue[j]) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int
+read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header)
+{
+ int errret = -1;
+
+ READ_FIXED (stream, header->Version);
+ READ_OFFSET (stream, header->GlyphClassDef);
+ READ_OFFSET (stream, header->AttachList);
+ READ_OFFSET (stream, header->LigCaretList);
+ READ_OFFSET (stream, header->MarkAttachClassDef);
+ return 0;
+}
+
+static void *
+read_gdef_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
+{
+ OTF_Stream *stream = table->stream;
+ char *errfmt = "GDEF%s";
+ void *errret = NULL;
+ OTF_GDEF *gdef;
+
+ OTF_CALLOC (gdef, 1, "");
+ if (stream->buf)
+ {
+ read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header);
+ if (gdef->header.GlyphClassDef)
+ {
+ gdef->glyph_class_def.offset = gdef->header.GlyphClassDef;
+ read_class_def_without_offset (otf, stream,
+ &gdef->glyph_class_def);
+ }
+ if (gdef->header.AttachList)
+ read_attach_list (otf, stream, gdef->header.AttachList,
+ &gdef->attach_list);
+ if (gdef->header.LigCaretList)
+ read_lig_caret_list (otf, stream, gdef->header.LigCaretList,
+ &gdef->lig_caret_list);
+ if (gdef->header.MarkAttachClassDef)
+ {
+ gdef->mark_attach_class_def.offset = gdef->header.MarkAttachClassDef;
+ read_class_def_without_offset (otf, stream,
+ &gdef->mark_attach_class_def);
+ }
+ }
+
+ *table->address = gdef;
+ return gdef;
+}
+
+\f
+/*** (1-7) Structures for ScriptList, FeatureList, and LookupList */
+
+static int
+read_script_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_ScriptList *list)
+{
+ char *errfmt = "Script List%s";
+ int errret = -1;
+ int i, j, k;
+
+ SEEK_STREAM (stream, offset);
+ READ_USHORT (stream, list->ScriptCount);
+ OTF_CALLOC (list->Script, list->ScriptCount, "");
+
+ for (i = 0; i < list->ScriptCount; i++)
+ {
+ READ_TAG (stream, list->Script[i].ScriptTag);
+ READ_OFFSET (stream, list->Script[i].offset);
+ }
+ for (i = 0; i < list->ScriptCount; i++)
+ {
+ OTF_Script *script = list->Script + i;
+ long script_offset = offset + script->offset;
+
+ SEEK_STREAM (stream, script_offset);
+ READ_OFFSET (stream, script->DefaultLangSysOffset);
+ READ_USHORT (stream, script->LangSysCount);
+ OTF_MALLOC (script->LangSysRecord, script->LangSysCount, " (LangSys)");
+ OTF_CALLOC (script->LangSys, script->LangSysCount, " (LangSys)");
+ for (j = 0; j < script->LangSysCount; j++)
+ {
+ READ_TAG (stream, script->LangSysRecord[j].LangSysTag);
+ READ_OFFSET (stream, script->LangSysRecord[j].LangSys);
+ }
+
+ if (script->DefaultLangSysOffset)
+ {
+ OTF_LangSys *langsys = &script->DefaultLangSys;
+
+ SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset);
+ READ_OFFSET (stream, langsys->LookupOrder);
+ READ_USHORT (stream, langsys->ReqFeatureIndex);
+ READ_USHORT (stream, langsys->FeatureCount);
+ OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
+ " (FeatureIndex)");
+ for (k = 0; k < langsys->FeatureCount; k++)
+ READ_USHORT (stream, langsys->FeatureIndex[k]);
+ }
+
+ for (j = 0; j < script->LangSysCount; j++)
+ {
+ OTF_LangSys *langsys = script->LangSys + j;
+
+ SEEK_STREAM (stream,
+ script_offset + script->LangSysRecord[j].LangSys);
+ READ_OFFSET (stream, langsys->LookupOrder);
+ READ_USHORT (stream, langsys->ReqFeatureIndex);
+ READ_USHORT (stream, langsys->FeatureCount);
+ OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
+ " (FeatureIndex)");
+ for (k = 0; k < langsys->FeatureCount; k++)
+ READ_USHORT (stream, langsys->FeatureIndex[k]);
+ }
+ }
+
+ return 0;
+}
+
+static int
+read_feature_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_FeatureList *list)
+{
+ char *errfmt = "Feature List%s";
+ int errret = -1;
+ int i, j;
+
+ SEEK_STREAM (stream, offset);
+ READ_UINT16 (stream, list->FeatureCount);
+ OTF_CALLOC (list->Feature, list->FeatureCount, "");
+ for (i = 0; i < list->FeatureCount; i++)
+ {
+ READ_TAG (stream, list->Feature[i].FeatureTag);
+ READ_OFFSET (stream, list->Feature[i].offset);
+ }
+ for (i = 0; i < list->FeatureCount; i++)
+ {
+ OTF_Feature *feature = list->Feature + i;
+
+ SEEK_STREAM (stream, offset + feature->offset);
+ READ_OFFSET (stream, feature->FeatureParams);
+ READ_UINT16 (stream, feature->LookupCount);
+ OTF_MALLOC (feature->LookupListIndex, feature->LookupCount,
+ " (LookupListIndex)");
+ for (j = 0; j < feature->LookupCount; j++)
+ READ_UINT16 (stream, feature->LookupListIndex[j]);
+ }
+
+ return 0;
+}
+
+static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream,
+ long offset, unsigned type,
+ OTF_LookupSubTableGSUB *subtable);
+static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
+ long offset, unsigned type,
+ OTF_LookupSubTableGPOS *subtable);
+
+static int
+read_lookup_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_LookupList *list, int gsubp)
+{
+ char *errfmt = "Lookup List%s";
+ int errret = -1;
+ int i, j;
+
+ SEEK_STREAM (stream, offset);
+ READ_UINT16 (stream, list->LookupCount);
+ OTF_CALLOC (list->Lookup, list->LookupCount, "");
+
+ for (i = 0; i < list->LookupCount; i++)
+ READ_OFFSET (stream, list->Lookup[i].offset);
+ for (i = 0; i < list->LookupCount; i++)
+ {
+ OTF_Lookup *lookup = list->Lookup + i;
+
+ SEEK_STREAM (stream, offset + lookup->offset);
+ READ_UINT16 (stream, lookup->LookupType);
+ READ_UINT16 (stream, lookup->LookupFlag);
+ READ_UINT16 (stream, lookup->SubTableCount);
+ OTF_MALLOC (lookup->SubTableOffset, lookup->SubTableCount,
+ " (SubTableOffset)");
+ if (gsubp)
+ OTF_CALLOC (lookup->SubTable.gsub, lookup->SubTableCount,
+ " (SubTable)");
+ else
+ OTF_CALLOC (lookup->SubTable.gpos, lookup->SubTableCount,
+ " (SubTable)");
+ for (j = 0; j < lookup->SubTableCount; j++)
+ READ_OFFSET (stream, lookup->SubTableOffset[j]);
+ for (j = 0; j < lookup->SubTableCount; j++)
+ {
+ long this_offset
+ = offset + lookup->offset + lookup->SubTableOffset[j];
+
+ if (gsubp
+ ? read_lookup_subtable_gsub (otf, stream, this_offset,
+ lookup->LookupType,
+ lookup->SubTable.gsub + j) < 0
+ : read_lookup_subtable_gpos (otf, stream, this_offset,
+ lookup->LookupType,
+ lookup->SubTable.gpos + j) < 0)
+ return errret;
+ }
+ }
+
+ return 0;
+}
+
+\f
+/*** (1-8) Structures common to GSUB and GPOS */
+
+static unsigned
+read_lookup_record_list (OTF *otf, OTF_Stream *stream,
+ OTF_LookupRecord **record, int count)
+{
+ char *errfmt = "LookupRecord%s";
+ unsigned errret = 0;
+ int i;
+
+ 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_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule)
+{
+ char *errfmt = "List of Rule%s";
+ unsigned errret = 0;
+ OTF_StreamState state;
+ unsigned count;