(enum OTF_ReaderFlag): New enum.
authorhanda <handa>
Thu, 19 May 2005 01:37:04 +0000 (01:37 +0000)
committerhanda <handa>
Thu, 19 May 2005 01:37:04 +0000 (01:37 +0000)
(OTF_TableInfo): Change the prototype of the member `reader'.
Caller changed.
(read_head_table, read_name_table, read_cmap_table)
(read_gdef_table): Adjusted for the change of OTF_TableInfo.
(read_feature_list): Seek the stream at first.
(read_gsub_gpos_table): Adjusted for the change of OTF_TableInfo.
Pay attention to the arg `flag'.
(read_gsub_table, read_gpos_table): Adjusted for the change of
OTF_TableInfo.
(OTF_get_table): Likewise.
(OTF_get_scripts, OTF_get_features, OTF_check_features): New
functions.

src/otfopen.c

index b6ba52e..7385805 100644 (file)
@@ -239,15 +239,26 @@ struct OTF_MemoryRecord
 
 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
 {
@@ -317,8 +328,9 @@ allocate_memory_record (OTF *otf)
 /*** (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;
@@ -331,6 +343,7 @@ read_head_table (OTF *otf, OTF_Stream *stream)
   READ_USHORT (stream, head->flags);
   READ_USHORT (stream, head->unitsPerEm);
 
+  *table->address = head;
   return head;
 }
 
@@ -408,8 +421,9 @@ read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec)
 }
 
 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;
@@ -445,6 +459,7 @@ read_name_table (OTF *otf, OTF_Stream *stream)
        name->name[nameID] = (char *) rec->name;
     }
 
+  *table->address = name;
   return name;
 }
 
@@ -452,8 +467,9 @@ read_name_table (OTF *otf, OTF_Stream *stream)
 /*** (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;
@@ -712,6 +728,7 @@ read_cmap_table (OTF *otf, OTF_Stream *stream)
       cmap->max_glyph_id = max_glyph_id;
     }
 
+  *table->address = cmap;
   return cmap;
 }
 
@@ -1045,8 +1062,9 @@ read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header)
 }
 
 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;
@@ -1070,6 +1088,7 @@ read_gdef_table (OTF *otf, OTF_Stream *stream)
       read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def);
     }
 
+  *table->address = gdef;
   return gdef;
 }
 
@@ -1150,6 +1169,7 @@ read_feature_list (OTF *otf, OTF_Stream *stream, long offset,
   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++)
@@ -1651,25 +1671,47 @@ read_chain_context3 (OTF *otf, OTF_Stream *stream, long offset,
 }
 
 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;
 }
 
@@ -1971,9 +2013,9 @@ read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset,
 }
 
 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
@@ -2499,9 +2541,9 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
 }
 
 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
@@ -2791,14 +2833,18 @@ int
 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;
@@ -2814,7 +2860,98 @@ OTF_check_table (OTF *otf, char *name)
   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 ***/