typedef struct OTF_MemoryRecord OTF_MemoryRecord;
-typedef struct
+enum OTF_ReaderFlag
+ {
+ OTF_READ_FULL,
+ OTF_READ_SCRIPTS,
+ OTF_READ_FEATURES,
+ OTF_READ_MAX,
+ };
+
+struct _OTF_TableInfo;
+typedef struct _OTF_TableInfo OTF_TableInfo;
+
+struct _OTF_TableInfo
{
/* Points to one of OTF->head, OTF->name, etc. */
void **address;
/* Function to read one of OTF tables. */
- void *(*reader) (OTF *otf, OTF_Stream *stream);
+ void *(*reader) (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag);
/* Stream given to <reader>. */
OTF_Stream *stream;
-} OTF_TableInfo;
+};
struct OTF_InternalData
{
/*** (1-2) "head" table */
static void *
-read_head_table (OTF *otf, OTF_Stream *stream)
+read_head_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
{
+ OTF_Stream *stream = table->stream;
char *errfmt = "head%s";
void *errret = NULL;
OTF_head *head;
READ_USHORT (stream, head->flags);
READ_USHORT (stream, head->unitsPerEm);
+ *table->address = head;
return head;
}
}
static void *
-read_name_table (OTF *otf, OTF_Stream *stream)
+read_name_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
{
+ OTF_Stream *stream = table->stream;
char *errfmt = "name%s";
void *errret = NULL;
OTF_name *name;
name->name[nameID] = (char *) rec->name;
}
+ *table->address = name;
return name;
}
/*** (1-4) "cmap" table */
static void *
-read_cmap_table (OTF *otf, OTF_Stream *stream)
+read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
{
+ OTF_Stream *stream = table->stream;
char *errfmt = "cmap%s";
void *errret = NULL;
OTF_cmap *cmap;
cmap->max_glyph_id = max_glyph_id;
}
+ *table->address = cmap;
return cmap;
}
}
static void *
-read_gdef_table (OTF *otf, OTF_Stream *stream)
+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;
read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def);
}
+ *table->address = gdef;
return gdef;
}
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++)
}
static void *
-read_gsub_gpos_table (OTF *otf, OTF_Stream *stream, int gsubp)
+read_gsub_gpos_table (OTF *otf, OTF_TableInfo *table, int gsubp,
+ enum OTF_ReaderFlag flag)
{
+ OTF_Stream *stream = table->stream;
char *errfmt = gsubp ? "GSUB%s" : "GPOS%s";
void *errret = NULL;
- OTF_GSUB_GPOS *gsub_gpos;
-
- OTF_CALLOC (gsub_gpos, 1, "");
- READ_FIXED (stream, gsub_gpos->Version);
- READ_OFFSET (stream, gsub_gpos->ScriptList.offset);
- READ_OFFSET (stream, gsub_gpos->FeatureList.offset);
- READ_OFFSET (stream, gsub_gpos->LookupList.offset);
-
- if (read_script_list (otf, stream, gsub_gpos->ScriptList.offset,
- &gsub_gpos->ScriptList) < 0
- || read_feature_list (otf, stream, gsub_gpos->FeatureList.offset,
- &gsub_gpos->FeatureList) < 0
- || read_lookup_list (otf, stream, gsub_gpos->LookupList.offset,
- &gsub_gpos->LookupList, gsubp) < 0)
+ OTF_GSUB_GPOS *gsub_gpos = *table->address;
+
+ if (gsub_gpos)
+ SEEK_STREAM (stream, 10);
+ else
+ {
+ SEEK_STREAM (stream, 0);
+ OTF_CALLOC (gsub_gpos, 1, "");
+ READ_FIXED (stream, gsub_gpos->Version);
+ READ_OFFSET (stream, gsub_gpos->ScriptList.offset);
+ READ_OFFSET (stream, gsub_gpos->FeatureList.offset);
+ READ_OFFSET (stream, gsub_gpos->LookupList.offset);
+ }
+
+ if (! gsub_gpos->ScriptList.Script
+ && read_script_list (otf, stream, gsub_gpos->ScriptList.offset,
+ &gsub_gpos->ScriptList) < 0)
return NULL;
+ if (flag != OTF_READ_SCRIPTS)
+ {
+ if (! gsub_gpos->FeatureList.Feature
+ && read_feature_list (otf, stream, gsub_gpos->FeatureList.offset,
+ &gsub_gpos->FeatureList) < 0)
+ return NULL;
+ if (flag != OTF_READ_FEATURES)
+ {
+ if (! gsub_gpos->LookupList.Lookup
+ && read_lookup_list (otf, stream, gsub_gpos->LookupList.offset,
+ &gsub_gpos->LookupList, gsubp) < 0)
+ return NULL;
+ }
+ }
+
+ if (! *table->address)
+ *table->address = gsub_gpos;
return gsub_gpos;
}
}
static void *
-read_gsub_table (OTF *otf, OTF_Stream *stream)
+read_gsub_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
{
- return read_gsub_gpos_table (otf, stream, 1);
+ return read_gsub_gpos_table (otf, table, 1, flag);
}
\f
}
static void *
-read_gpos_table (OTF *otf, OTF_Stream *stream)
+read_gpos_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
{
- return read_gsub_gpos_table (otf, stream, 0);
+ return read_gsub_gpos_table (otf, table, 0, flag);
}
\f
OTF_get_table (OTF *otf, char *name)
{
OTF_TableInfo *table_info = get_table_info (otf, name);
+ void *address;
if (! table_info)
return -1;
+ if (! table_info->stream)
+ /* Already fully loaded. */
+ return 0;
- *table_info->address = (*table_info->reader) (otf, table_info->stream);
+ address = (*table_info->reader) (otf, table_info, OTF_READ_FULL);
free_stream (table_info->stream);
table_info->stream = NULL;
- if (! *table_info->address)
+ if (! address)
{
table_info->reader = NULL;
return -1;
return (get_table_info (otf, name) ? 0 : -1);
}
+/*** (2-5) OTF_get_scripts() */
+
+int
+OTF_get_scripts (OTF *otf, int gsubp)
+{
+ OTF_TableInfo *table_info
+ = (otf->internal_data->table_info
+ + (gsubp ? OTF_TABLE_TYPE_GSUB : OTF_TABLE_TYPE_GPOS));
+ void *address;
+
+ if (! table_info->reader)
+ return -1;
+ if (! table_info->stream)
+ /* Already fully loaded. */
+ return 0;
+ address = (*table_info->reader) (otf, table_info, OTF_READ_SCRIPTS);
+ if (! address)
+ {
+ table_info->reader = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+/*** (2-6) OTF_get_features() */
+
+int
+OTF_get_features (OTF *otf, int gsubp)
+{
+ OTF_TableInfo *table_info
+ = (otf->internal_data->table_info
+ + (gsubp ? OTF_TABLE_TYPE_GSUB : OTF_TABLE_TYPE_GPOS));
+ void *address;
+
+ if (! table_info->reader)
+ return -1;
+ if (! table_info->stream)
+ /* Already fully loaded. */
+ return 0;
+
+ address = (*table_info->reader) (otf, table_info, OTF_READ_FEATURES);
+ if (! address)
+ {
+ table_info->reader = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+/*** (2-7) OTF_check_features */
+
+int
+OTF_check_features (OTF *otf, int gsubp,
+ OTF_Tag script, OTF_Tag language, OTF_Tag *features,
+ int n_features)
+{
+ OTF_ScriptList *script_list;
+ OTF_Script *Script = NULL;
+ OTF_LangSys *LangSys = NULL;
+ OTF_FeatureList *feature_list;
+ int i, j;
+
+ if (OTF_get_features (otf, gsubp) < 0)
+ return -1;
+ script_list = &otf->gsub->ScriptList;
+ feature_list = &otf->gsub->FeatureList;
+ for (i = 0; i < script_list->ScriptCount && ! Script; i++)
+ if (script_list->Script[i].ScriptTag == script)
+ Script = script_list->Script + i;
+ if (! Script)
+ return 0;
+ if (language)
+ {
+ for (i = 0; i < Script->LangSysCount && ! LangSys; i++)
+ if (Script->LangSysRecord[i].LangSysTag == language)
+ LangSys = Script->LangSys + i;
+ }
+ if (! LangSys)
+ LangSys = &Script->DefaultLangSys;
+ for (j = 0; j < n_features; j++)
+ {
+ OTF_Tag feature = features[j];
+
+ for (i = 0; i < LangSys->FeatureCount; i++)
+ if (feature_list->Feature[i].FeatureTag == feature)
+ break;
+ if (i == LangSys->FeatureCount)
+ return 0;
+ }
+ return 1;
+}
\f
/*** (5) API miscellaneous ***/